GH GambleHub

Garantias de entrega de webhooks

Webhooks - notificações asinhrônicas «sistema para assinante» HTTP (S). A rede não é confiável: as respostas são perdidas, os pacotes vêm duplicados ou fora da ordem. Por isso, as garantias de entrega não são construídas «por TCP», mas no nível de protocolo de webhooks e idempotação de domínio.

O objetivo principal é fornecer uma entrega at-least-once com ordem de chave (onde for necessário), fornecer ao assinante materiais de tratamento idumpotente e uma ferramenta de reconstituição.


1) Níveis de garantia

Best-effort é uma tentativa descartável, sem retais. Aceitável apenas para eventos «irrelevantes».
At-least-once (recomendado) - Pode ser duplicado e out-of-order, mas o evento será entregue desde que o assinante esteja disponível dentro de um prazo razoável.
Effectively-exactly-once (ao nível do efeito) - obtido com uma combinação de idempotação e armazenamento dedup no lado do assinante/remetente. Não é possível usar HTTP «exactly-once» no transporte.


2) Contrato de webhook: mínimo necessário

Cabeçalhos (exemplo):

X-Webhook-Id: 5d1e6a1b-4f7d-4a3d-8b3a-6c2b2f0f3f21  # глобальный ID события
X-Delivery-Attempt: 3                 # номер попытки
X-Event-Type: payment.authorized.v1          # тип/версия
X-Event-Time: 2025-10-31T12:34:56Z          # ISO8601
X-Partition-Key: psp_tx_987654            # ключ порядка
X-Seq: 418                      # монотонный номер по ключу
X-Signature-Alg: HMAC-SHA256
X-Signature: t=1730378096,v1=hex(hmac(secret, t        body))
Content-Type: application/json
Corpo (exemplo):
json
{
"id": "5d1e6a1b-4f7d-4a3d-8b3a-6c2b2f0f3f21",
"type": "payment.authorized.v1",
"occurred_at": "2025-10-31T12:34:56Z",
"partition_key": "psp_tx_987654",
"sequence": 418,
"data": {
"payment_id": "psp_tx_987654",
"amount": "10.00",
"currency": "EUR",
"status": "AUTHORIZED"
},
"schema_version": 1
}

A exigência do destinatário é responder rapidamente '2xx' após o tampão e validação da assinatura, e o processamento do negócio é assincrónico.


3) Ordem e causalidade

Ordem da chave: a garantia «não sai» apenas dentro de um 'partition _ key' (por exemplo, 'player _ id', 'wallet _ id', 'psp _ tx _ id').
A ordem global não é garantida.
No lado do remetente, há uma fila com uma seriada por chave (um consumidor/charding), inbox com '(fonte, event _ id)' no lado do destinatário e espera opcionalmente por 'seq' omitidos.

Se as omissões são críticas, forneça pull-API 'GET/events? after = checkpoint 'para o status «perseguir e encurtar».


4) Idempotidade e dedução

Cada webhook leva um 'X-Webhook-Id' estável.
O destinatário armazena 'inbox': PK - 'fonte + event _ id'; repetições → no-op.
Os efeitos secundários (gravação no banco de dados/carteira) são executados apenas uma vez na primeira «visão» do evento.
Para comandos de efeito, use o Idempotency-Key e a caixa de resultados durante a janela de retais.


5) Retraias, backoff e janelas

Política de retrações (arbitragem):
  • Retrair em '5xx/timeout/connect error/409-Conflict (retryable )/429'.
  • Não retraia em '4xx' exceto '409/423/429' (e somente com a semântica acordada).
  • Backoff exponencial + full jitter: 0. 5s, 1s, 2s, 4s, 8s, … até 'max = 10-15 min'; As janelas de retrações TTL, por exemplo, 72 horas.
  • Respeitar 'Retry-After' no destinatário.
  • Compartilhar «reconhecer um evento não entregue» e traduzi-lo para o DLQ.
yaml retry:
initial_ms: 500 multiplier: 2.0 jitter: full max_delay_ms: 900000 ttl: 72h retry_on: [TIMEOUT, 5xx, 429]

6) DLQ и redrive

DLQ - «cemitério» de eventos venenosos ou vencidos por TTL com metainformação completa (paylad, manchetes, erros, tentativas, hachês).
Console Web/API para redrive (reaproveitamento por pontos) com edição opcional de endpoint/segredo.
Rate-limited redrive e batch-redrive com prioridade.


7) Segurança

mTLS (se possível) ou TLS 1. 2+.

Assinatura corporal (HMAC com segredo per tenant/endpoint). Verificação:

1. Extrair 't' (timestamp) do cabeçalho, verificar uma janela deslizante (por exemplo, £5 min).

2. Restaurar linha de assinatura 'tbody ', comparar HMAC em constant-time.
Anti-replay: armazenar '(event _ id, t)' e rejeitar pedidos muito antigos/repetidos.
Rotação de segredos - suporte de dois segredos ativos durante o período de rotação.
Opcional: IP-allowlist, cabeçalho «User-Agente», dedução origin-IP.

8) Quotas, rate limits e justiça

Fair-Queue per tenant/subscriber: Para garantir que um assinante/tenante não marca um pool comum.
Quotas e limites burst para o tráfego de saída e per-endpoint.
Reação a '429': honrar 'Retry-After', trotar o fluxo; Se a limitação for prolongada, degrade (envio apenas de tipos críticos de eventos).


9) Ciclo de vida da assinatura

Register/Verify: POST endpoint → challenge/response ou confirmação out-of-band.
Lease (opcional): a assinatura é válida até 'valid _ to'; A extensão é clara.
Secret rotation: `current_secret`, `next_secret` с `switch_at`.
Teste ping: evento artificial para verificar a rota antes de incluir os topics principais.
Health-amostras: HEAD/GET periódico com verificação do perfil latency e TLS.


10) Evolução dos circuitos (versões de eventos)

Versionização do tipo de evento: 'payment. authorized. v1` → `…v2`.
Evolução - aditivo (novos campos → MENOR API), breaking → novo tipo.
Registro de esquema (JSON-Schema/Avro/Protobuf) + validação automática antes do envio.
A manchete 'X-Event-Estando' e o campo 'schema _ versão' no corpo são ambos obrigatórios.


11) Observabilidade e SLO

Métricas (tipo/tenante/assinante):
  • `deliveries_total`, `2xx/4xx/5xx_rate`, `timeout_rate`, `signature_fail_rate`.
  • 'attempts _ avg', 'p50/p95/p99 _ delivery _ latency _ ms' (da publicação até 2xx).
  • `dedup_rate`, `out_of_order_rate`, `dlq_rate`, `redrive_success_rate`.
  • `queue_depth`, `oldest_in_queue_ms`, `throttle_events`.
SLO (árbitro):
  • Proporção de entregas ≤ 60 c (p95) - 99. 5% para eventos críticos.
  • DLQ ≤ 0. 1% em 24 h.
  • Signature failures ≤ 0. 05%.

Логи/трейсинг: `event_id`, `partition_key`, `seq`, `attempt`, `endpoint`, `tenant_id`, `schema_version`, `trace_id`.


12) Algoritmo arbitral do remetente

1. Gravar evento em outbox transacionado.
2. Definir partition _ key e seq; colocar na fila.
3. O worker pega na chave, forma o pedido, assina, envia com os temporizadores (connect/read).
4. Em '2xx' - admitir entregue, fixar latência e seq-checkpoint.
5. Com '429/5xx/timeout' - retrai de acordo com a política.
6. Por TTL → DLQ e alert.


13) Processador de arbitragem (destinatário)

1. Aceitar solicitação, verificar TLS/proto.
2. Validação da assinatura e da janela do tempo.
3. ACK rápido 2xx (após gravação sincronizada em inbox/fila local).
4. O worker asinhrônico lê 'inbox', verifique 'event _ id', se necessário - ordena por 'seq' dentro de 'partition _ key'.
5. Executa efeitos, escreve «offset/seq checkpoint» para o recôncil.
6. Em caso de erro, retraias locais; tarefas «venenosas» → DLQ local com alertas.


14) Reconcile (contorno de pula)

Para incidentes «impraticáveis»:
  • `GET /events? partition _ key =... & after _ seq =... & limit =... '- dar todos os omitidos.
  • Token-checkpoint: 'after = opaque _ tocen' em vez de seq.
  • Redelivery idimpotente: os mesmos 'event _ id', a mesma assinatura do novo 't'.

15) Títulos e códigos úteis

2xx - aceitou (mesmo que o processamento empresarial seja posterior).
410 Gone - endpoint fechado (o remetente interrompe a entrega e marca a assinatura como «arquivo»).
409/423 - bloqueio temporário do recurso → retrai é inteligente.
429 - muitas vezes → TNT e backoff.
400/401/403/404 - erro de configuração; Parar a retraia, abrir o tíquete.


16) Multi-tenante e regiões

Filas individuais e limites per tenant/endpoint.
Data residency: envio da região de dados; cabeçalho «X-Tenant», «X-Region».
Isolamento de falhas: a queda de um assinante não afeta os outros (separate pools).


17) Testes

Contract testes: exemplos fixos de corpos/assinaturas, verificação de validação.

Chaos: drop/duplicado, shuffle de ordem, atrasos de rede, 'RST', 'TLS'

Load: tempestade burst, paragem p95/p99.
Segurança: anti-réplicas, timestamp obsoletos, segredos errados, rotação.
DR./Replay: redrive em massa de DLQ em um estande isolado.


18) Playbooks (runbooks)

1. Altura de 'marca _ fail _ rate'

Verificar a deriva do relógio que expirou 'tolerance', rotação de segredos; ativar temporariamente «dual secret».

2. Fila envelhecida ('oldest _ in _ queue _ ms' ↑)

Aumentar os workers, priorizar topics críticos, reduzir temporariamente a frequência de tipos ruidosos.

3. Tempestade '429' junto ao assinante

Incluir trottling e pausas entre tentativas; Mover tipos de eventos menos críticos.

4. Massa '5xx'

Abrir o circuito-breaker para um endpoint específico, para o modo defer & batch; sinal ao assinante.

5. Preencher DLQ

Parar a publicação não crítica, incluir batch-redrive com RPS baixo, levantar alertas para os donos de assinaturas.


19) Erros típicos

Processamento pesado sincronizado até a resposta 2xx → retraí e duplicação.
Não há assinatura de corpo/janela do tempo → vulnerabilidade à troca/réplica.
Falta de 'event _ id' e 'inbox' → não é possível tornar a idempotação.
A tentativa de ordem global → os bloqueios das filas para sempre.
Retraias sem jitter/limites → aumento do incidente (thundering herd).
Um único pool comum em todos os seguidores → «barulhento» coloca todos.


20) Folha de cheque antes de vender

  • Contrato: 'event _ id', 'partition _ key', 'seq', 'event _ tipo. vN ', assinatura HMAC e timestamp.
  • Remetente: outbox, seriado por chave, retraí com backoff + jitter, TTL, DLQ e redrive.
  • Destinatário: gravação rápida em inbox + 2xx; tratamento idêntico; DLQ local.
  • Segurança: TLS, assinaturas, anti-réplicas, dual-secret, rotação.
  • Quotas/limites: fair-queue per tenant/endpoint, respeito 'Retry-After'.
  • Recôncil API e checkpoint; documentação para assinantes.
  • Observabilidade: p95/fluxos/erros/DLQ, rastreamento por 'event _ id'.
  • Versionização de eventos e política de evolução de esquemas.
  • Playbooks de incidentes e «botão» de pausa/descongelamento global.

Conclusão

Webhooks confiáveis são um protocolo sobre HTTP, não apenas «POST com JSON». Contrato claro (ID, chave de ordem, assinatura), idempotidade, retraí com jitter, fila justa e playbooks bem resolvidos transformam o «melhor caso» em um mecanismo de entrega previsível e mensurável. Construa at-least-once + ordem à chave + recôncil, e o sistema irá sobreviver com calma à rede, picos de carga e erros humanos.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.