バッジバックフィルコード

ここではバッジのバックフィル処理を見ています:

特に、以下のクエリに問題があるようです(Long-Running Sidekiq Jobs を参照)。

    sql = <<~SQL
      DELETE FROM user_badges
        WHERE id IN (
          SELECT ub.id
          FROM user_badges ub
          LEFT JOIN (
            #{badge.query}
          ) q ON q.user_id = ub.user_id
          #{post_clause}
          WHERE ub.badge_id = :id AND q.user_id IS NULL
        )
    SQL

このクエリは LEFT JOIN を使用しているため、一致の有無に関わらず user_badges のすべての結果が返されます。しかし、この部分が非常に混乱を招きます:

ON q.user_id = ub.user_id
...
AND q.user_id IS NULL

このクエリは user_id が一致する行で結合を行いますが、その後 WHERE 句でそれらの行を破棄してしまいます。そのため、その結合は実質的に無意味になっています。そこで疑問に思う点は以下の通りです:

  1. バックフィル関数の目的は何ですか?処理中のバッジを完全に削除し、一度に再構築しているように見えます。これは必要でしょうか?

  2. この関数において、投稿を対象とするバッジとそうでないバッジの違いは何ですか?LEFT JOIN を使用している場合、再構築のために削除する正しい badge_id を特定する際に、これは本当に重要でしょうか?

「いいね!」 3