Jobs::SyncTopicUserBookmarked in un loop utilizzando il 100% della CPU

Nell’ultimo ~18h, il nostro server sta utilizzando quasi il 100% della CPU.

Guardando Sidekiq, è impegnato nell’esecuzione degli stessi 5 job:

È sempre in “Just now” e sembrano essere sempre in riesecuzione sugli stessi 3 ID di argomento.

Ho provato a riavviare Discourse, ma la situazione è rimasta invariata.

Non sono sicuro se sia correlato, ma questo è iniziato ~24 ore dopo l’aggiornamento da 3.3.3 a 3.3.4. Non vedo modifiche recenti a app/jobs/regular/sync_topic_user_bookmarked.rb e non ho potuto individuare alcuna modifica in 3.3.4 che potesse essere correlata, ma non conosco il codebase.

Qualche idea su cosa potrebbe succedere?

Un aggiornamento a questo. Abbiamo appena notato che gli ID dei 3 argomenti su cui i task continuano a essere rieseguiti sono argomenti ai quali abbiamo attivato l’eliminazione automatica delle risposte ieri, vicino a quando è iniziato questo. Sono tutti argomenti molto grandi.

Quindi conosciamo il trigger, ma l’SQL che viene ripetuto non sembra eseguire alcun batch, quindi non capisco perché venga rieseguito più e più volte.

Questo viene attivato da qualche altro job che sta ancora eliminando il gran numero di risposte e Jobs::SyncTopicUserBookmarked viene eseguito per ogni singolo post eliminato? O si tratta di un bug?

Abbiamo rimosso l’eliminazione automatica da uno degli argomenti di grandi dimensioni e non sembra aver avuto alcun effetto sulle chiamate ripetute di Jobs::SyncTopicUserBookmarked su quell’ID di argomento.

Ho ridotto SIDEKIQ_WORKERS a 2 e, poco dopo, la coda (con molte cose in sospeso) si è svuotata e non ci sono più Jobs::SyncTopicUserBookmarked in esecuzione… :thinking:

Prima di provare, ho notato che la query seguente veniva eseguita più volte contemporaneamente (utilizzando lo stesso topic id):

SELECT bookmarks.user_id, COUNT(*)
INTO TEMP TABLE tmp_sync_topic_user_bookmarks
FROM bookmarks
LEFT JOIN posts ON posts.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Post'
LEFT JOIN topics ON (topics.id = bookmarks.bookmarkable_id AND bookmarks.bookmarkable_type = 'Topic') OR
 (topics.id = posts.topic_id)
WHERE (topics.id = 51303 OR posts.topic_id = 51303)
AND posts.deleted_at IS NULL AND topics.deleted_at IS NULL
GROUP BY bookmarks.user_id;

UPDATE topic_users
SET bookmarked = true
FROM tmp_sync_topic_user_bookmarks
WHERE topic_users.user_id = tmp_sync_topic_user_bookmarks.user_id AND
  topic_users.topic_id = 51303 AND
  tmp_sync_topic_user_bookmarks.count > 0;

UPDATE topic_users
SET bookmarked = false
FROM tmp_sync_topic_user_bookmarks
WHERE topic_users.topic_id = 51303 AND
  topic_users.bookmarked = true AND
  topic_users.user_id NOT IN (
    SELECT tmp_sync_topic_user_bookmarks.user_id
    FROM tmp_sync_topic_user_bookmarks
  );

DROP TABLE tmp_sync_topic_user_bookmarks;

Non mi è chiaro come PostgreSQL esegua più istruzioni in una singola query, ma se venisse eseguita più volte contemporaneamente, potrebbe causare un loop in qualche modo?