Flush de progresso nunca rodou em produção

O que aconteceu

O progresso de áudio, aula, live e meditação é acumulado no Redis e deve ser gravado no banco por uma rotina periódica. Em produção essa rotina nunca executou: a cada minuto o agendador enfileirava o flush e o worker rejeitava a mensagem com Received unregistered task. A mensagem voltava para a fila e era reentregue indefinidamente — a do log tinha 32 tentativas. Na prática, o progresso dos usuários ficava retido no Redis sem nunca chegar ao banco.

Causa raiz

O autodiscovery do Celery importa apenas o módulo apps.<app>.tasks de cada app. Quando tasks é um pacote, isso significa importar só o __init__.py. O apps/engagements/tasks/__init__.py importava os submódulos de áudio, aula, live e meditação, mas não o flush — então flush_pending_progress e save_progress_batch nunca entravam no registro de tasks do worker.

O mesmo vale para o agendador: sem a task registrada, ele publicava pelo nome sem enxergar o queue= do decorator, mandando a mensagem para a fila padrão em vez da fila de progresso.

Correção

O __init__.py do pacote passou a importar as duas tasks do flush. Isso resolve os dois sintomas de uma vez: o worker registra as tasks e o agendador volta a rotear para a fila de progresso.

Como evitar

  • Ao quebrar um tasks.py em pacote tasks/, todo submódulo com task precisa ser importado no __init__.py — o autodiscovery não desce sozinho
  • Ao adicionar um submódulo novo de task, importar no __init__.py no mesmo commit
  • Um agendamento que referencia a task por caminho pontilhado não garante que ela exista: o nome no beat schedule só é validado em runtime, pelo worker

Referências