Pular para conteúdo

0016 — Watchdog de silêncio de webhook

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-04 · Decidido em: 2026-09-04

Revisada pela 0023 (2026-09-21). O limite de 24h úteis decidido aqui não enxerga um apagão de poucas horas dentro do expediente — o de 18/09/2026 durou 2h44 no pico de uma sexta e custou quatro pedidos. A 0023 soma uma régua comercial (minutos, seg–sex 8h–18h) e baixa o intervalo do job de 1h para 5min; o limite de 24h úteis descrito abaixo continua valendo como rede do apagão que começa fora do horário. A causa provável também ficou mais larga: não só 404, timeout também desativa o webhook na PIED.

Contexto

O webhook da PIED (POST /webhook/pied) é a via tempo-real da captura. Há um modo de falha silencioso e recorrente: quando o endpoint responde 404 (nossos servidores fora do ar num deploy/reinício), a PIED desativa o webhook e para de enviar — e não volta sozinha. O conserto é manual: alguém da Maxsul acessa o dashboard da PIED, exclui e recadastra o webhook (runbook). Enquanto ninguém percebe, pedidos deixam de chegar em tempo real (o poll REST é backstop, mas roda a cada 6h e não cobre tudo).

Não havia nada vigiando esse silêncio — a falha só aparecia quando alguém notava pedidos faltando.

Decisão

Um watchdog (watchdog/WatchdogJob, @Scheduled + guarda de cluster 0014) que compara max(pied_webhook.recebido_em) com agora e alerta se o silêncio passar do limite.

  • Tempo útil, não corrido. O gap conta só dias de semana (seg–sex; sáb/dom não contam — watchdog/TempoUtil, fuso America/Sao_Paulo). A Maxsul pode não trabalhar no fim de semana: 48h de silêncio que caem num sábado+domingo não são problema. Limite default 24h úteis, configurável (PIED_WATCHDOG_LIMITE_HORAS).
  • Canal: GlitchTip. O alerta é um LOG.error(...) → captado pelo SentryAppender (nível ERROR). Sem e-mail (o 0005 já cobre erro de negócio por e-mail; aqui é saúde de infra, que vive no GlitchTip).
  • 1x por episódio. Alerta uma vez ao cruzar o limite e não repete até chegar um webhook novo (o max(recebido_em) avança e abre outro episódio). Estado persistido em pied_watchdog_estado (singleton), para não re-alertar a cada rodada nem em restart.
  • Mensagem acionável. O texto do alerta já diz a causa provável (PIED desativou após 404) e a ação (excluir + recadastrar), apontando o runbook.
  • Nasce ligado (PIED_WATCHDOG_HABILITADO=true): o webhook nasce ligado, então vigiá-lo é o padrão esperado. Se o webhook está desabilitado (pied.webhook.habilitado=false), o watchdog não alerta (não há o que vigiar).

Alternativas consideradas

  • Tempo corrido (24h absolutas): rejeitada — dispararia falso-positivo toda segunda de manhã depois de um fim de semana normal sem pedidos.
  • Horário comercial (8–18h), não dia inteiro: rejeitada por ora — a Maxsul pediu o eixo semanal (dia útil), não o de horas; dia útil = 24h mantém o cálculo simples e sem config de expediente. Reabrir se surgir necessidade.
  • Alerta por e-mail: preterido — é saúde de infra, não rejeição de pedido; GlitchTip é o lugar. Fácil somar e-mail depois (o AlertaService já existe) se quiserem.
  • Auto-recadastrar o webhook via API da PIED: fora de alcance — o cadastro do webhook é manual no dashboard da PIED (não há endpoint documentado). O laço é alerta → ação humana.

Consequências

  • Silêncio de webhook vira visível (GlitchTip) em ~1 dia útil, com instrução de conserto no próprio alerta.
  • Novo estado singleton pied_watchdog_estado (migration V10), novo lock de cluster pied_watchdog.
  • Ponto cego aceito: se nunca chegou webhook, o baseline é a subida do app (reinicia a cada restart) — só relevante num app que nunca recebeu webhook algum.