Vai al contenuto principale

Riprovare una richiesta senza doppio effetto

L'idempotenza permette di riprovare una richiesta POST senza temere un doppio effetto. Un client che perde la risposta per timeout può riprovare con la stessa chiave di idempotenza, è l'API restituisce la risposta memorizzata invece di eseguire nuovamente l'handler. CaptainDNS segue la convenzione Stripe, con una finestra di validità di 24 ore.

Perché usare l'idempotenza

Le reti non sono affidabili. Un client può:

  • Inviare una richiesta che ha successo lato server ma la cui risposta si perde.
  • Andare in crash durante un retry automatico.
  • Vedere un timeout dal load balancer mentre l'API ha già processato la richiesta.

Senza idempotenza, si deve scegliere tra non riprovare (perdendo operazioni legittime) o riprovare ciecamente (eseguendo la stessa operazione più volte). L'idempotenza offre una terza via: riprovare in sicurezza.

Come usarla

Aggiungi un header Idempotency-Key alla tua richiesta 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"}

La chiave deve essere una stringa opaca tra 10 e 255 caratteri. Gli UUIDv4 sono ideali.

Comportamento lato server

Alla prima richiesta, il middleware calcola lo sha256 del body, scrive il record (api_key_id, idempotency_key, request_hash) dopo il successo è cattura status è body della risposta.

Alla seconda richiesta con la stessa chiave:

  1. Il middleware trova il record esistente.
  2. Se l'hash del nuovo body corrisponde: replay. La risposta memorizzata viene restituita con X-Idempotent-Replay: true.
  3. Se l'hash differisce: conflitto. L'API restituisce 409 IDEMPOTENCY_CONFLICT.

Un replay consuma zero crediti è non invoca l'handler sottostante.

Finestra di validità

I record vivono 24 ore. Dopo, un job di purge li rimuove è una chiave riutilizzata invoca l'handler normalmente.

Metodi coperti

L'idempotenza si applica solo ai metodi mutativi o costosi. In pratica, tutti gli endpoint pubblici CaptainDNS sono POST, quindi tutti sono ammissibili. L'header Idempotency-Key e opzionale.

Conflitti

Un 409 IDEMPOTENCY_CONFLICT si verifica quando una chiave viene riutilizzata con un body diverso. Per evitarlo:

  • Calcola la chiave prima di serializzare il body.
  • Non mescolare chiamate diverse sotto la stessa chiave.
  • Se il tuo framework riordina le chiavi JSON, fissa l'ordine manualmente.

Esempi d'uso

Retry dopo timeout di rete

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 in coda di job

job = fetch_next_job()
idempotencyKey = hash(job.id)
response = post(url, job.payload, headers={"Idempotency-Key": idempotencyKey})
mark_job_done(job.id, response)

Batch con dedup lato server

for domain in domains:
    idempotencyKey = "batch-" + run_id + "-" + domain
    post(url, {"domain": domain}, headers={"Idempotency-Key": idempotencyKey})

Limitazioni

  • 24 h di storage: oltre, il replay non è più possibile.
  • Scope per chiave API: due chiavi diverse con lo stesso valore non collidono.
  • Nessuna coordinazione tra server: più backend devono coordinare le chiavi.
  • Identita stretta del body: uno spazio in più rompe l'hash.

Prossimi passi

Procedi con i codici d'errore per capire come reagire a 409 IDEMPOTENCY_CONFLICT, o consulta la referenza OpenAPI.