Я изучаю процесс восполнения бейджей, который происходит здесь:
https://github.com/discourse/discourse/blob/master/app/services/badge_granter.rb
В частности, следующий запрос, похоже, содержит некоторые проблемы (см. 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, делая такое соединение бессмысленным. Поэтому я задаюсь вопросом:
-
Какова цель функции восполнения? Похоже, она полностью удаляет обрабатываемый бейдж, а затем заново строит его целиком. Необходимо ли это?
-
В чем разница между бейджем, который ориентирован на сообщения, и бейджем, который не ориентирован на сообщения, в контексте этой функции? При использовании LEFT JOIN имеет ли это вообще значение при поиске правильного badge_id для удаления перед повторной сборкой?