Seu primeiro job agendado
No #24 vimos por que o Trigger.dev existe. Agora a parte prática: como nasce um job agendado no nosso stack, do nada até rodar de verdade. Este post é o "mão na massa" do módulo.
O esqueleto de um job
Um job agendado tem três pedaços:
- O gatilho — quando rodar (um cron) ou o que dispara (um evento).
- A lógica — o que fazer quando acorda (ler dados, chamar IA, gravar resultado).
- O resultado — o que fica gravado pra app consumir.
A IA escreve esse esqueleto rápido. Você guia com contexto: "um job diário às 6h que lê X, resume com Claude e grava em Y".
O cron sem cair na pegadinha do fuso
Aqui mora uma das nossas pegadinhas favoritas: timezone. Um cron "0 6 * * *" sem fuso roda no fuso do servidor — que não é Brasília. No Trigger.dev, a gente declara o agendamento como objeto com { pattern, timezone } pra rodar no horário certo do Brasil. Esqueça isso e o "resumo das 6h" chega às 3h.
A regra que vem antes do código: idempotência
Job pode rodar mais de uma vez (retry, redeploy, disparo manual). Se "gerar o resumo de hoje" rodar duas vezes e criar dois resumos, você tem bug. Então a lógica precisa ser idempotente:
- Checar se já existe o registro do dia antes de criar.
- Usar
upsertem vez deinsertcego. - Ter chave que identifica "isso já foi feito".
Isso conversa direto com a regra da casa: antes de criar dado, cheque o que já existe.
Testar antes de confiar
- Dispare manualmente primeiro, veja o resultado.
- Olhe o log da execução (observabilidade do Trigger.dev).
- Só então deixe no automático — e mesmo assim, acompanhe as primeiras rodadas.
A divisão de trabalho
IA escreve o job; você define frequência, fuso e idempotência, e valida a primeira execução. São essas três coisas que separam um job confiável de um gerador de plantão noturno.
⚠️ Armadilha #25: escrever o job assumindo que ele roda exatamente uma vez. Ele não roda. Job que não é idempotente é uma bomba-relógio que duplica dado no primeiro retry.
Próximo da série: #26 — Workflows com retry e observabilidade.