Mover para baixo para 4f7f9ef87cbcd574144f657dd43b7e705d98ff8e de fato resolveu os workers do sidekiq PostAlert travados e as preocupações com OOM: os poucos jobs do PostAlert que são enfileirados agora são concluídos em questão de segundos, não minutos.
Olá, sim, isso espero que resolva este problema. Testei esta solução em 3 fóruns, e uma nova consulta foi sempre muito mais rápida e não sobrecarregou os servidores.
Obrigado por relatar este problema e, por favor, me avise se você ainda tiver problemas.
Infelizmente, mesmo com essas alterações, ainda estamos vendo os trabalhos do PostAlert levarem muito mais tempo do que antes e travarem completamente os workers do Sidekiq durante o processamento.
(temos mais de 10 milhões de linhas de usuários e algumas categorias silenciadas por padrão, então há muitos silenciamentos configurados!)
Reverter os três commits que recentemente tocaram este trabalho e reiniciar o contêiner, enquanto isso, faz com que os trabalhos sejam concluídos normalmente.
Acabei de mesclar outra tentativa de melhorar o desempenho deste job:
Eu testei em algumas instâncias e funcionou bem, mas elas eram menores que a sua.
Se ainda estiver falhando com este commit, você poderia me fornecer o relatório EXPLAIN ANALYSE? Script para gerá-lo:
topic = Topic.last
user_option_sql_fragment =
if SiteSetting.watched_precedence_over_muted
<<~SQL
INTERSECT
SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS false
SQL
else
<<~SQL
EXCEPT
SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS true
SQL
end
user_ids_sql = <<~SQL
(
SELECT user_id FROM category_users WHERE category_id = #{topic.category_id.to_i} AND notification_level = #{CategoryUser.notification_levels[:muted]}
UNION
SELECT user_id FROM tag_users tu JOIN topic_tags tt ON tt.tag_id = tu.tag_id AND tt.topic_id = #{topic.id} WHERE tu.notification_level = #{TagUser.notification_levels[:muted]}
EXCEPT
SELECT user_id FROM topic_users tus WHERE tus.topic_id = #{topic.id} AND tus.notification_level = #{TopicUser.notification_levels[:watching]}
)
#{user_option_sql_fragment}
SQL
sql = User.where("id IN (#{user_ids_sql})").to_sql
sql_with_index = <<~SQL
EXPLAIN ANALYZE #{sql};
SQL
result = ActiveRecord::Base.connection.execute("#{sql_with_index}")
puts sql_with_index
result.each do |r|
puts r.values
end
Isso me ajudaria a encontrar um índice ausente ou qual parte desta consulta está tão lenta.