Celery countdown/ETA com SQS e visibility_timeout
O que aconteceu
Ao desenhar o debounce de progresso, a primeira ideia foi agendar um flush por usuário com countdown=30. Esse desenho duplicaria execuções e ainda manteria O(usuários ativos) tasks na fila — foi descartado antes de ser implementado.
Causa raiz
Com broker SQS, tasks Celery com countdown/eta são recebidas pelo worker e ficam retidas sem ack até o horário agendado. Se o atraso for maior ou igual ao visibility_timeout da fila (neste projeto: 30s, em config/celery_settings.py), o SQS reentrega a mensagem a outro worker — e a task executa duplicada.
Correção
O debounce por usuário com countdown foi substituído por flush periódico via Celery beat, lendo o estado pendente do Redis (padrão flush_pending_progress em apps/engagements/tasks.py).
Como evitar
- Nunca usar
countdown/eta≥visibility_timeoutcom broker SQS - Para trabalho adiado/coalescido, preferir flush periódico via Celery beat lendo estado pendente do Redis
- Tasks que processam lotes devem terminar bem abaixo do
visibility_timeout(lotes pequenos e configuráveis) e ser idempotentes, pois reentrega rara ainda é possível comCELERY_ACKS_LATE = True