Pular para conteúdo

Crons e Jobs Agendados — Fonte única da verdade

Última revisão: 2026-04-21

Este documento lista todos os jobs automatizados da Gita e serve como guia operacional: quem, onde, quando, como desativar.

Três sistemas rodam jobs:

  1. Easypanel — apiclickup (/Users/juniormaia/gita/server/) — automações de negócio, webhooks, crons node-cron.
  2. Easypanel — engine-gita-agents (/Users/juniormaia/projetos/gita-agents/packages/engine/) — pipeline multi-tenant de agentes WhatsApp + follow-up loop.
  3. Launchd no Mac do Junior (~/Library/LaunchAgents/com.juniormaia.*.plist) — briefings/relatórios locais. Ver LAUNCHD.md.

Controle visual de 1 e 2 → Admin panel em /crons (https://admin.gita.work/crons).


Arquitetura de controle

Cada cron tem duas camadas de ativação (ambas precisam estar on pra rodar):

Camada Onde mexe Quando usar Efeito
Env flag (ENABLE_<ID>) Easypanel → serviço → Environment Master switch. Desligar em incidente grave. Exige redeploy. Se off, o cron nem é registrado no node-cron
Runtime toggle Admin /crons (grava em Supabase crons_config) Pausar/ligar no dia-a-dia sem redeploy Reflete em até 30s (cache). Cron registra normalmente, mas o handler pula.

Regra de ouro

Pra desligar um cron: primeiro toggle no admin. Se não resolver (porque o handler ainda dispara para logs, webhooks etc), desliga a env flag no Easypanel.

Pra ligar um cron que estava fora: garante que a env flag tá on no Easypanel + toggle on no admin. Se o server foi deployed com a flag off, precisa redeploy (não basta mudar a var, o Easypanel só aplica no restart).


Servidor 1 — apiclickup (/gita/server/)

Registry declarativo: server/crons.js. Adicionar cron novo significa editar esse arquivo + criar o handler em automations/.

id Label Schedule Env flag Default Arquivo Integrações
scheduled-reports Relatório financeiro diário 9h BRT seg–sex (0 12 * * 1-5 UTC) ENABLE_SCHEDULED_REPORTS off automations/scheduled-reports.js Uazapi · Google Sheets · Supabase
vendas-reconcile Reconciliação Hotmart 10h BRT diário (0 13 * * * UTC) ENABLE_VENDAS_RECONCILE on automations/vendas-reconcile.js Hotmart · Supabase
diagnostico-sequencia Sequência 7 dias diagnóstico a cada hora :15 (15 * * * *) ENABLE_DIAGNOSTICO_SEQUENCIA on automations/diagnostico-sequencia.js Anthropic · Uazapi · Supabase

Endpoints úteis

  • GET /status — estado atual de todos os crons (env + runtime + lastRun).
  • GET /reports/cron-status — diagnóstico só do relatório financeiro.
  • GET /vendas/reconcile/status — diagnóstico da reconciliação.
  • GET /diagnostico/sequencia/status — diagnóstico da sequência.
  • POST /reports/send-daily — dispara relatório financeiro agora.
  • POST /vendas/reconcile/run?dias=7 — dispara reconciliação agora.
  • POST /diagnostico/sequencia/processar — dispara sequência agora.
  • GET /audit?event=cron.<id> — histórico de execuções.
  • POST /crons/invalidate { id? } — invalida cache de crons_config (admin chama automaticamente após toggle).

Servidor 2 — engine-gita-agents (/projetos/gita-agents/packages/engine/)

id Label Schedule Env flag Default Arquivo
followup-loop Follow-up automático de leads a cada 60s ENABLE_FOLLOWUP_LOOP on engine/src/index.ts:337

Endpoints úteis

  • GET /status — lista o cron com estado env + runtime.
  • POST /crons/invalidate { id? } — invalida cache.

Não há endpoint manual de "disparar agora" — loop dispara em 60s.


Como investigar um cron que não rodou

  1. Abrir /crons no admin. Ver estado efetivo (env + runtime) e lastRun.
  2. Se env=off: flag está desligada no Easypanel → abrir console do Easypanel → Environment → ligar → redeploy.
  3. Se runtime=off: toggle no admin pra ligar (reflete em 30s).
  4. Se ambos on mas lastRun antigo: server pode estar fora do ar. Checar com curl https://<host>/health ou ver o serviço no Easypanel.
  5. Se lastRun recente mas status=error: abrir GET /audit?event=cron.<id> pra ver o detalhe.
  6. Se tudo "correto" mas nada acontece: confere se o commit deployado inclui seu código (/status.deployCommit vs git log HEAD).

Como adicionar um cron novo (apiclickup)

  1. Criar handler em server/automations/<novo-cron>.js seguindo o padrão dos existentes:
  2. Exporta (app) => { /* endpoints manuais, cron, audit */ }
  3. Lê env flag: const CRON_ENABLED = process.env.ENABLE_<NOVO> !== 'false'
  4. Dentro do tick, checa await cronsConfig.isEnabled('<novo-cron>') e pula se false
  5. Loga em audit-log com evento cron.<novo-cron>
  6. Registrar em server/crons.js com metadados (id, label, description, cronExpr, envFlag, defaultEnabled, integrations, manualEndpoint, statusEndpoint).
  7. Adicionar o módulo em server/automations/index.js.
  8. Declarar a env flag em server/.env.example.
  9. Se default=on, inserir seed no Supabase: INSERT INTO crons_config (id, server, enabled) VALUES ('<novo>', 'apiclickup', true).
  10. Testar: npm run dev no server, chamar endpoint manual, ver GET /status mostrando novo cron.
  11. Subir e forçar redeploy no Easypanel.

Como adicionar um cron novo (engine)

Padrão ainda ad-hoc (só follow-up existe). Se virar recorrente, extrair registry como no apiclickup. Por enquanto, editar engine/src/index.ts direto:

  1. Adicionar flag ENABLE_<NOVO> em .env.example.
  2. Criar setInterval condicional ao flag + isEnabled('<novo>') do services/crons-config.ts.
  3. Registrar em GET /status no array crons.
  4. Adicionar seed em crons_config via migration.

Troubleshooting — Incidente de referência (21/04/2026)

Sintoma: Junior recebeu relatório financeiro às 9h mesmo após pedir desativação.

Causa raiz: o commit aecedbb (18/04) comentou scheduledReports(app) em automations/index.js — mas o Easypanel do apiclickup não foi redeployado. Produção continuou rodando o boot anterior.

Correção permanente (esta refatoração): - Env flag ENABLE_SCHEDULED_REPORTS=false default. - Runtime toggle via admin se precisar ligar/desligar sem redeploy. - /status mostra deployCommit — dá pra ver se o deploy pegou o último commit. - Endpoint /reports/cron-status agora retorna enabled: false quando está desligado (antes mentia).