구글 게시글에 대해 알림이 잘못 생성됩니다

어제 갑자기 내 사이트에서 오래된 게시물에 대한 알림이 생성되기 시작했습니다. 최근 며칠간 1시간 이상 지난 후에 생성된 ‘게시됨’ 알림(notification_type = 9)의 수는 다음과 같습니다:

표를 생성하기 위해 사용한 쿼리
WITH pre AS (
	SELECT
		p.id as post_id,
		to_char(n.created_at,
			'YYYY-MM-DD') AS notified_day,
		p.topic_id,
		round(least(EXTRACT(EPOCH FROM n.created_at - p.created_at)::numeric, EXTRACT(EPOCH FROM n.created_at - p.updated_at)::numeric) / 3600)  AS hours_diff,
		p.created_at,
		p.updated_at,
		n.created_at,
		u.username
	FROM
		notifications n
	LEFT JOIN posts p ON p.post_number = n.post_number
		AND p.topic_id = n.topic_id
	left join users u on u.id = n.user_id
WHERE
	round(least(EXTRACT(EPOCH FROM n.created_at - p.created_at)::numeric, EXTRACT(EPOCH FROM n.created_at - p.updated_at)::numeric) / 3600) > 0
	AND n.notification_type = 9
ORDER BY
	n.created_at DESC
LIMIT 400
)
SELECT
	count(*), 
	notified_day
FROM
	pre
GROUP BY
	notified_day
ORDER BY
	notified_day DESC

다음은 몇 가지 예시입니다(위 쿼리의 CTE를 실행하여 얻은 결과):

첫 번째 강조된 행은 12월 8일에 생성되었지만, 해당 카테고리를 보고 있는 사용자가 12월 25일에 알림을 받았습니다(다른 사용자들에게 따르면, 그들은 이미 본 게시물에 대해 알림을 받고 있다고 합니다).

두 번째 강조된 행은 9월 29일에 생성되고 하루 후에 수정되었으며, 12월 25일에 알림이 전송되었습니다.

방금 컨테이너를 다시 구축했으므로 현재 최신 버전의 Discourse를 실행 중입니다. 일단 이메일 알림을 비활성화했습니다.

이 문제를 어떻게 해결해야 할지 아이디어가 있을까요? 어떤 이유로든 큐가 쌓인 경우이거나 그런 종류의 문제라고 추정합니다. 이러한 알림을 생성하는 원인을 파악하는 방법이 있을까요?

제 추측으로는, 과거에 어떤 이유로 실패했던 sidekiq 작업들이 이제야 실행되고 있는 것 같습니다. 아마도 무언가를 "수정"해서, 원래 보내야 할 시점이 아닌 지금에야 해당 알림들이 발송되고 있는 것으로 보입니다. /sidekiq 페이지를 확인하여 처리되기 전에 삭제할 수 있는 작업이 있는지 살펴보세요.

훌륭한 추측이에요, 제이. 최근 며칠간 사용자가 문제를 보고한 시점에 증가세가 확인됩니다:

예약 큐를 확인해 봤는데, 처리되지 않은 메시지가 길게 쌓여 있는 상황은 아닌 것 같습니다. 대신, 이러한 오래된 알림이 10분마다 수십 건씩 추가되는 것으로 보입니다.

이 알림을 Sidekiq로 보내는 원인을 추적할 수 있을까요?

몇일 후 문제가 스스로 해결되는 것처럼 보였지만(다행히도), 더 깊이 파고들면서 초기 SQL 쿼리가 불완전하다는 사실을 깨달았습니다: notifications.post_number 필드는 특정 주제에서 읽지 않은 첫 번째 게시물을 가리키지만, 새 게시물이 생성될 때마다 notification.created_at은 새로운 posts.created_at으로 업데이트됩니다.

이것은 제가 목격했던 시간 차이 중 일부를 설명해 주었지만, misteriously 나타났다가 사라진 급증 현상은 설명하지 못했습니다.

쿼리를 수정하려면, 먼저 post_timings를 확인하여 해당 사용자가 본 최신 topic_id/post_number를 찾아야 하고, notifications에서 가져온 값 대신 그 created_at을 사용해야 합니다.