Reexecutar uma requisição sem duplo efeito
A idempotência permite reexecutar uma requisição POST sem temer um duplo efeito. Um cliente que perde a resposta por timeout pode retentar com a mesma chave de idempotência, e a API retorna a resposta armazenada em vez de executar o handler novamente. CaptainDNS segue a convenção Stripe, com janela de validade de 24 horas.
Por que usar idempotência
As redes não são confiáveis. Um cliente pode:
- Enviar uma requisição que tem sucesso no servidor, mas cuja resposta se perde.
- Cair no meio de um retry automático.
- Ver um timeout no load balancer mesmo que a API já tenha processado.
Sem idempotência, você escolhe entre não reenviar (é perder operações legítimas) ou reenviar cegamente (é executar várias vezes). A idempotência oferece uma terceira via: reenviar com segurança.
Como usar
Adicione um header Idempotency-Key à sua requisição POST:
POST /public/v1/deliverability/score HTTP/1.1
Host: api.captaindns.com
Authorization: Bearer cdns_live_a3f2XK7mN9QrVtZ4yP1sH6eL8cF2dB5aR3gW7kJxM
Content-Type: application/json
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{"email":"contact@captaindns.com"}
A chave deve ser uma string opaca entre 1 e 255 caracteres ASCII imprimíveis sem espaço. Os UUID v4 ou ULID continuam recomendados como best practice (entropia suficiente, colisões estatisticamente impossíveis), mas qualquer identificador único no lado cliente serve.
Comportamento no servidor
Na primeira requisição, o middleware calcula o sha256 do body, grava o registro (api_key_id, idempotency_key, request_hash) após o sucesso e captura status e body da resposta.
Na segunda requisição com a mesma chave:
- O middleware encontra o registro existente.
- Se o hash do novo body corresponde: replay. A resposta armazenada é retornada com
X-Idempotent-Replay: true. - Se o hash difere: conflito. A API retorna
409 IDEMPOTENCY_CONFLICT.
Um replay consome zero créditos e não dispara o handler subjacente.
Janela de validade
Os registros vivem 24 horas. Após esse prazo, um job de purge os remove e uma chave reutilizada executa o handler normalmente.
Métodos cobertos
A idempotência só se aplica a métodos mutativos ou custosos. Na prática, todos os endpoints públicos CaptainDNS são POST. O header Idempotency-Key é opcional.
Conflitos
Um 409 IDEMPOTENCY_CONFLICT é disparado quando uma chave é reutilizada com body diferente. Para evitar:
- Calcule a chave antes de serializar o body.
- Não misture chamadas diferentes sob a mesma chave.
- Se seu framework reordena as chaves JSON, fixe a ordem manualmente.
Exemplos de uso
Retry após timeout de rede
idempotencyKey = uuid()
for attempt in 1..3:
try:
response = post(url, body, headers={"Idempotency-Key": idempotencyKey})
return response
except TimeoutError:
sleep(2 * attempt)
raise
Deduplicação em fila de jobs
job = fetch_next_job()
idempotencyKey = hash(job.id)
response = post(url, job.payload, headers={"Idempotency-Key": idempotencyKey})
mark_job_done(job.id, response)
Batch com dedupe no servidor
for domain in domains:
idempotencyKey = "batch-" + run_id + "-" + domain
post(url, {"domain": domain}, headers={"Idempotency-Key": idempotencyKey})
Limitações
- 24 h de armazenamento: depois disso, o replay não é mais possível.
- Escopo por chave API: duas chaves diferentes com o mesmo valor não colidem.
- Sem coordenação entre servidores: vários backends devem coordenar as chaves.
- Identidade estrita do body: um espaço a mais quebra o hash.
Próximos passos
Siga com os códigos de erro para entender como reagir a 409 IDEMPOTENCY_CONFLICT, ou consulte a referência OpenAPI.