Retentativas, skipped e DLQ

Para: Dev · Adm — Conferido em 2026-10-18.

Toda resposta que não seja 2xx faz o Dracma tentar de novo, com intervalos crescentes e um pequeno acréscimo aleatório, por até 72 horas. Depois disso o evento vai para a DLQ e continua recuperável. Esta página traz o cronograma, os estados de uma entrega, o que é skipped e como reabrir uma entrega.

O que é

Uma entrega é o registro de um evento a enviar para a URL da operação; uma tentativa é um POST dessa entrega. Cada tentativa tem 10 segundos no total (conexão, TLS e resposta). O resultado é:

  • Sucesso: qualquer resposta 2xx (200 a 299).
  • Falha: qualquer outra coisa: 3xx (o redirect não é seguido), 4xx, 5xx, estouro dos 10 s, erro de rede ou de TLS, nome que não resolve ou resolve para endereço bloqueado.

Nenhum código de status é "definitivo". Um 400, 401 ou 410 do seu receptor não faz o Dracma desistir: ele repete no cronograma até a DLQ. O corpo da resposta é lido até 64 KiB e descartado; só o status importa.

Estados de uma entrega

Estado Significado
pending Aguardando a primeira tentativa ou a próxima.
delivered O seu receptor respondeu 2xx.
dlq As tentativas se esgotaram sem 2xx.
skipped O evento foi registrado, mas nada foi enviado (veja abaixo).
stateDiagram-v2 [*] --> pending: URL cadastrada e tipo assinado [*] --> skipped: sem URL, outro ambiente ou tipo não assinado pending --> delivered: 2xx pending --> pending: falha, próxima tentativa agendada pending --> dlq: a próxima tentativa passaria de 72 h pending --> skipped: ambiente da URL difere do do evento dlq --> pending: reentrega (novo ciclo de 72 h) skipped --> pending: reentrega no sandbox delivered --> [*]

Quando usar

Leia esta página para dimensionar o receptor (quanto tempo ele pode ficar fora do ar sem perder entregas), para entender por que um evento "não chegou" e para recuperar uma DLQ. O que fazer quando um evento esgota o ciclo está na seção DLQ.

Como funciona

Cronograma e jitter

Depois de cada tentativa que falha, a próxima é agendada para espera-base + jitter a partir do horário agendado da tentativa anterior. A espera-base é:

30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 8 h e, depois disso, 8 h a cada tentativa.

O jitter é um acréscimo aleatório, só positivo, de 0 a 10 % da espera-base, em segundos inteiros. Ele espalha a carga no seu receptor; a espera-base é um piso (nenhuma tentativa sai antes dela). A tabela mostra o instante de cada tentativa, contado desde a primeira, sem jitter e com o jitter máximo:

Tentativa Espera-base Jitter Instante (sem jitter) Instante (jitter máximo)
1 imediata n/a 0:00:00 0:00:00
2 30 s até +3 s 0:00:30 0:00:33
3 2 min até +12 s 0:02:30 0:02:45
4 10 min até +1 min 0:12:30 0:13:45
5 30 min até +3 min 0:42:30 0:46:45
6 1 h até +6 min 1:42:30 1:52:45
7 2 h até +12 min 3:42:30 4:04:45
8 4 h até +24 min 7:42:30 8:28:45
9 8 h até +48 min 15:42:30 17:16:45
10 8 h até +48 min 23:42:30 26:04:45
11 8 h até +48 min 31:42:30 34:52:45
12 8 h até +48 min 39:42:30 43:40:45
13 8 h até +48 min 47:42:30 52:28:45
14 8 h até +48 min 55:42:30 61:16:45
15 8 h até +48 min 63:42:30 70:04:45
16 8 h até +48 min 71:42:30 não ocorre

Os instantes estão em horas:minutos:segundos desde a primeira tentativa. O Dracma verifica as entregas vencidas em ciclos curtos, então o horário real de envio pode se atrasar um pouco além do agendado; esse atraso não é cumulativo, porque a contagem parte do horário agendado.

A janela de 72 horas

O ciclo tem 72 horas a partir da primeira tentativa. O Dracma nunca agenda uma tentativa depois dessas 72 h: se a próxima passaria do limite, a entrega vai para a DLQ. Na prática:

  • um ciclo tem 15 ou 16 tentativas no total (a 16ª só existe se o jitter acumulado ficar abaixo de cerca de 17 minutos, o que é raro);
  • a última tentativa sai entre cerca de 63 h 42 min e 71 h 42 min depois da primeira;
  • o evento entra na DLQ logo depois de a última tentativa falhar, portanto antes das 72 h.

Não dependa do horário exato de nenhuma tentativa. Se o seu receptor ficar indisponível por menos de cerca de 63 horas, a entrega ainda acerta quando ele voltar.

Concorrência e rajadas

Entregas de eventos diferentes são independentes e concorrem entre si. O Dracma não oferece limite de vazão por endpoint nem fila ordenada por objeto. Uma rajada (por exemplo, muitos depósitos pagos ao mesmo tempo) chega como muitas requisições em sequência rápida, e as tentativas pendentes de eventos antigos misturam-se com as de eventos novos. Dimensione o receptor para absorver o pico: grave o evento em uma fila local e responda 2xx rápido.

Não disponível

O Dracma não permite configurar limite de taxa, concorrência máxima ou janela de entrega por endpoint.

skipped: o evento foi registrado e nada foi enviado

Uma entrega fica skipped (com um skip_reason) quando o Dracma decide, por regra, não enviar:

skip_reason Quando
no_endpoint A operação não tinha URL cadastrada quando o evento nasceu.
environment_mismatch O ambiente da URL (teste ou real) difere do ambiente do evento.
event_not_subscribed A URL tem uma lista de tipos assinados e o tipo do evento não está nela.

Três pontos que costumam surpreender:

  • Não é retroativo. Eventos que nasceram antes de você cadastrar a URL ficam skipped para sempre; cadastrar a URL depois não os envia. Recupere-os por GET /events.
  • Filtro de tipos. A assinatura de eventos é uma lista de tipos do Catálogo de eventos. Lista vazia significa todos os tipos. Um tipo fora da lista nunca é enviado por webhook, mas aparece em GET /events. Quem assina só deposit.paid não recebe deposit.under_review nem deposit.expired; o job de recuperação precisa tratar todos os tipos.
  • Nada é retentado. skipped não entra no cronograma e não vai para a DLQ.

DLQ: evento que esgotou as tentativas

Quando o ciclo termina sem 2xx, a entrega passa a dlq. O evento não se perde: o objeto continua consultável na API, o evento continua em GET /events e a entrega pode ser reaberta. O ciclo de vida:

  1. Alerta. Se a operação tem endereços de alerta cadastrados (até 5), o Dracma envia um e-mail "Webhook em DLQ" com o tipo e o id do evento. Sem endereços de alerta, nenhum e-mail sai.
  2. Visibilidade. A entrega aparece na aba de DLQ do painel, com o histórico de tentativas (número, horário, status HTTP, duração e erro resumido). Veja Webhooks no painel.
  3. Reentrega. No painel, quem tem permissão de gerenciar webhooks pode pré-visualizar e reentregar eventos da DLQ, até 50 por vez. A reentrega reabre um ciclo novo de 72 h, com o mesmo Dracma-Event-Id e os mesmos bytes de corpo, para a URL que estiver cadastrada naquele momento (nunca para outra URL).
  4. Resolução. Um evento da DLQ que você tratou por outro caminho (por exemplo, pelo job de GET /events) pode ser marcado como resolvido, com um motivo de 10 a 1000 caracteres. Isso não reenvia nada; só tira o item da lista de pendentes e guarda a justificativa.

Reentrega de evento já entregue

No painel, só eventos que estão na DLQ podem ser reentregues. Um evento já delivered não é reaberto em produção. Na operação de teste, a ação de reentrega do sandbox reabre eventos em qualquer estado (pending, skipped, dlq ou delivered); veja Sandbox.

Como a reentrega manual pode acontecer muito depois do evento original, a sua deduplicação não deve depender só de uma memória curta. Guarde os Dracma-Event-Id por no mínimo 7 dias (o ciclo de 72 h mais folga para uma reentrega) e mantenha o efeito idempotente também pelo external_id, que é uma segunda barreira.

Exemplos

Receptor fora do ar por 3 horas. A primeira tentativa falha às 14:00:00. As seguintes saem por volta de 14:00:30, 14:02:30, 14:12:30, 14:42:30, 15:42:30 e 17:42:30 (somando o jitter, cada uma pode atrasar até 10 % da espera). Se o receptor voltar às 17:00, a tentativa de 17:42 já recebe o 2xx e a entrega fica delivered.

Receptor com bug permanente. Se o seu receptor responde 400 para todo evento, o Dracma repete 15 ou 16 vezes em cerca de três dias e então coloca o evento na DLQ, com e-mail de alerta. Corrija o bug, reentregue a DLQ pelo painel e confirme que o job de GET /events não deixou lacuna.

URL cadastrada depois do primeiro depósito. Os eventos anteriores ao cadastro ficam skipped com no_endpoint. Eles não chegam por webhook; o job de GET /events os entrega ao seu receptor.

Erros e casos de borda

  • Falha sem código HTTP. A tentativa pode falhar antes de o POST sair: a URL deixou de passar na política, o nome resolve para um endereço bloqueado ou a operação não tem segredo de webhook ativo (nada é enviado sem assinatura). O erro aparece no log de entregas e a tentativa conta no cronograma. Gere o primeiro segredo antes de esperar eventos (veja Segredo e rotação).
  • 2xx com leitura da resposta interrompida. Se a conexão cair no meio da resposta, mesmo com status 2xx, a tentativa pode ser contada como falha. Responda curto e feche a conexão normalmente.
  • Erros "permanentes" geram tempestade. Um receptor que responde 4xx para um evento que nunca vai aceitar recebe 15 ou 16 tentativas e um alerta de DLQ. Para um evento que você não quer tratar, responda 200.
  • Corpo da resposta. Não devolva informação útil esperando que o Dracma a use; o corpo é descartado.
  • Os dados mudaram entre tentativas. O corpo é o mesmo em todas; para saber o estado atual, consulte a API.

Veja também