Hemos encontrado un problema en un sitio de Discourse autoalojado en el que el ReactionLikeSynchronizer parece estar provocando errores 500/504 para las acciones de los usuarios.
El trabajo parece estar eliminando repetidamente las mismas 26.766 reacciones de PostAction cada hora, aunque todas ellas ya hayan sido marcadas como eliminadas. Durante estas sincronizaciones más largas, las solicitudes normales de los usuarios parecen bloquearse en PostgreSQL y alcanzar el tiempo de espera de 30 segundos de Pitchfork.
Entorno
- Discourse autoalojado en la versión v2026.10.0-latest-277-ge1f6bd561
- PostgreSQL 18.4
discourse_reactions_like_sync_enabled = true- Se trata de un sitio antiguo, por lo que hay muchos datos históricos de reacciones
Informes de usuarios
- A veces las reacciones fallan y producen el mensaje «Algo salió mal».
- A veces los temas que un usuario visitó permanecen marcados como no leídos.
- Los informes se concentran alrededor de una vez por hora, al inicio de cada hora.
Registros y datos
13:58:58 ReactionLikeSynchronizer starts
13:59:50 Pitchfork worker timeout / 500
14:00:02 Pitchfork worker timeout / 500
14:00:18 Pitchfork worker timeout / 500
14:00:48 ReactionLikeSynchronizer completes
15:00:09 sync starts
15:01:16 request timeout / 500
15:01:40 request timeout / 500
15:01:45 sync completes
Salida del sincronizador
Inserted 0 post action likes, recovered 0 trashed post action likes. (0 total)
Trashed 26766 post action likes.
Cabe destacar que la misma cantidad de 26.766 aparece en cada ejecución que revisé.
Contenido de la base de datos
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE pa.deleted_at IS NULL) AS currently_active,
COUNT(*) FILTER (WHERE pa.deleted_at IS NOT NULL) AS already_trashed
FROM post_actions pa
JOIN discourse_reactions_reaction_users ru
ON ru.user_id = pa.user_id
AND ru.post_id = pa.post_id
JOIN discourse_reactions_reactions r
ON r.id = ru.reaction_id
WHERE pa.post_action_type_id = 2
AND r.reaction_value IN (
'-1','poop','face_with_symbols_on_mouth','enraged_face',
'face_vomiting','nauseated_face','angry','kitchen_knife',
'water_pistol','bomb','clown_face','unamused_face','roll_eyes',
'confused','smirking_face','disappointed_face','pensive_face',
'lying_face','weary_face','tired_face','confounded_face',
'persevering_face','smiling_face_with_horns','angry_face_with_horns',
'cigarette','person_gesturing_no','prohibited','no_entry',
'dagger','cross_mark'
);
total | currently_active | already_trashed
-------+------------------+-----------------
26766 | 0 | 26766
Notas
Por lo que vale, parece que ReactionLikeSynchronizer#trash_excluded_post_actions coincide con reacciones que han sido excluidas, incluso si ya han sido eliminadas. La consulta es la siguiente:
UPDATE post_actions
SET deleted_at = NOW()
FROM discourse_reactions_reaction_users ru
INNER JOIN discourse_reactions_reactions
ON discourse_reactions_reactions.id = ru.reaction_id
WHERE post_actions.user_id = ru.user_id
AND post_actions.post_id = ru.post_id
AND post_actions.post_action_type_id = :like
AND discourse_reactions_reactions.reaction_value IN (:excluded_from_like)
RETURNING post_actions.id
Cabe destacar que esto no excluye las acciones eliminadas mediante algo como AND post_actions.deleted_at IS NULL.
Esto parece resultar en que el mismo conjunto de filas se reprocesa cada hora. Puedo agregar una traza de pila si es necesario.
Como solución temporal, he deshabilitado discourse_reactions_like_sync_enabled y estoy monitoreando si los errores dejan de ocurrir cada hora.