ゲーミフィケーションと招待

Gamificationプラグインを使用すると、招待が引き換えられた際にポイントが付与されます。
これは、招待状を送信し、複製(偽)のアカウントで引き換えることによって簡単に悪用できます。
そのような偽のアカウントが管理者によって削除された場合、gamificationプラグイン(および招待システム)の動作は、招待状がどのように送信されたかによって異なります。

  • 招待が特定のメールアドレスに関連付けられていた場合、ユーザーが削除されると、inviteレコードとuser_inviteレコードの両方が完全に削除されます。次にSidekiqのUpdateScoresFor*ジョブが実行されると、gamificationプラグインは、付与されたポイントをスコアから差し引きます

  • 招待が特定のメールアドレスに関連付けられていなかった場合、invited_usersレコードは削除されますが、inviteレコードは残ります。redemption_countの値は減少しません。招待の引き換えは実際に行われたため、ユーザーが後で削除されたとしても、これはある意味で理にかなっています。ただし、Gamificationプラグインはredemption_countを使用してスコアを計算するため、ポイントは差し引かれません

これをデバッグしている際に、スコアジョブは10日未満の招待のみを考慮することもわかりました。したがって、招待が11日後に引き換えられた場合、ポイントはまったく付与されません。「created_atの代わりにupdated_atを見る必要があるだろう」と言うつもりでしたが、招待の引き換え数が増加しても、updated_atタイムスタンプは更新されません。

「いいね!」 11

これらの線に沿ったものでうまくいくでしょうか(採点可能なクエリ形式に調整されています - これはデータエクスプローラー用のテストです :slight_smile:):

-- [params]
-- date :start_date
-- date :end_date

SELECT
    invited_by_id AS user_id,
    COUNT(*) AS user_invites,
    COUNT(*) * 10 AS invite_score
FROM invited_users iu
  JOIN invites i ON i.id = iu.invite_id
  JOIN users u ON u.id = iu.user_id
WHERE iu.redeemed_at::date BETWEEN :start_date AND :end_date
  AND iu.user_id <> i.invited_by_id
  AND u.created_at > iu.redeemed_at
GROUP BY invited_by_id
ORDER BY user_invites DESC

ユーザーが削除されると、invited_users テーブルからクリアされるため、カウントに含まれなくなります。削除が10日以内に行われた場合、自動的に修正されますが、それより長くかかった場合は手動でのスコア更新が必要になります。

redeemed_at 日付を使用すると、10日以上前に作成された招待も考慮されます。

AND iu.user_id <> i.invited_by_id は、自己招待も除外します。

users テーブルを結合し、AND u.created_at > iu.redeemed_at を追加すると、既存のユーザーを招待することも除外されます。

「いいね!」 3

それは良いアプローチですが、一つ問題があります。

これはうまく機能しません。ユーザーが作成されたのが、引き換えが行われたよりわずかに前である場合があります。理由は不明ですが、ほとんどの場合は10分の1秒ですが、10秒の差が見つかったこともあります。

実際のデータベースでテストしました。

select
  iu.redeemed_at iu_AS redeemed_at,
  u.created_at AS u_created_at,
  u.created_at > iu.redeemed_at AS u_created_gt_iu_redeemed
from invited_users iu
left join users u on u.id = iu.user_id
where iu.redeemed_at is not null
order by iu.id desc;
       iu_redeemed_at       |        u_created_at        | u_created_gt_iu_redeemed
----------------------------+----------------------------+--------------------------
 2023-09-08 00:00:47.557057 | 2023-09-08 00:00:48.376446 | t
 2023-08-25 20:09:03.486362 | 2023-08-25 20:09:03.201357 | f
 2023-08-15 23:38:32.271709 | 2023-08-15 23:38:33.570299 | t
 2023-08-14 10:44:34.19912  | 2023-08-14 10:44:35.429371 | t
 2023-08-12 13:41:10.428013 | 2023-08-12 13:41:11.733973 | t
 2023-07-31 17:58:13.511289 | 2023-07-31 17:57:50.427111 | f
 2023-07-23 00:56:33.455185 | 2023-07-23 00:55:47.999263 | f
 2023-07-19 08:42:44.908096 | 2023-07-19 08:42:46.040201 | t
 2023-06-30 09:11:38.829692 | 2023-06-30 09:11:39.618586 | t
 2023-06-30 08:37:02.322192 | 2023-06-30 08:37:03.133769 | t
 2023-06-29 16:24:01.705616 | 2023-06-29 16:24:02.55067  | t
 2023-06-29 12:53:33.245688 | 2023-06-29 12:53:34.067159 | t
「いいね!」 1

それは興味深いですね。まったく考慮していませんでした。:slight_smile:

AND u.created_at + INTERVAL '1 SECOND' > iu.redeemed_at のような小さなバッファを追加することで、それほど影響を与えずに補うことはできますか?

何が遅延の原因となっているのかわからないため、これは「ブラックマジック」すぎるように思います。

遅延は、大規模なサイドキックキューかそれに類するものによって引き起こされていると疑っています。大多数は1秒未満ですが、約3%は0:00:01~0:15:00(1秒~15分)の範囲にあります。

そして、半分のパーセントは数日単位であり、これは私たちが防ごうとしている種類の乱用のように見えます。したがって、これは効果的ですが、偽陽性の量のために、良いことよりも悪いことの方が多いでしょう。

「いいね!」 2

これで解決するはずです。

「いいね!」 1

これはバグというよりは別の機能リクエストのように思えます。(cc @Falco)

このトピックは3日後に自動的に閉じられました。新しい返信はもう許可されていません。