Pular para o conteúdo principal

Idempotency

Falhas de rede acontecem. A maneira segura de fazer retry de uma chamada à API sem risco de duplicação é usar o header Idempotency-Key — o DVS reconhece esse header e faz deduplicação em uma janela de 24 horas.

Como funciona

  1. Gere um UUID no client por operação lógica (uma classification, uma validation).
  2. Envie-o no header Idempotency-Key em todo retry dessa operação.
  3. Caso seja feito retry e o DVS já tenha processado a request original, o DVS retorna a response original sem reprocessar.
curl -X POST https://dvs-ingestion-api.sandbox.osigu.com/v1/classification-requests \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479" \
...

Quando o DVS faz deduplicação

CenárioComportamento do DVS
Mesmo Idempotency-Key, mesmo body, em até 24hRetorna a response em cache. Sem novo processamento. Sem nova cobrança.
Mesmo Idempotency-Key, body diferente, em até 24hRetorna 409 071-409-idempotency-mismatch.
Mesmo Idempotency-Key, após 24hTratado como nova request. A chave é reutilizada.
Idempotency-Key diferente, mesmo bodyCria uma nova request.

Boas práticas

Gere a chave no limite da operação

Gere uma única vez quando for decidido "vou chamar o DVS para classificar este documento". Reutilize-a em qualquer retry dessa mesma chamada. Não regenere a cada retry — isso anula o propósito.

UUID v4 é suficiente

Sem complicar — uuid.uuid4() ou crypto.randomUUID() são suficientes. Evite IDs sequenciais (previsíveis).

Persista a chave junto da operação

Armazene a chave no banco de dados junto da operação que ela representa. Em recuperação após crash, é possível fazer retry com segurança lendo a chave persistida.

Uma chave por operação, não por request

Se a aplicação envia 1000 classifications, gere 1000 chaves. Não compartilhe chaves entre documentos diferentes.

Race conditions

Caso duas requests paralelas cheguem ao DVS com o mesmo Idempotency-Key, apenas uma é processada; a outra aguarda a primeira concluir (até 5 segundos) e retorna a mesma response. Esse comportamento é seguro, mas adiciona latência — procure serializar os retries no client.

Exemplo: loop de retry seguro

import uuid, time, httpx

def classify_with_retry(token, body, max_attempts=3):
idempotency_key = str(uuid.uuid4()) # UMA chave por operação lógica
for attempt in range(max_attempts):
try:
return httpx.post(
"https://dvs-ingestion-api.sandbox.osigu.com/v1/classification-requests",
headers={
"Authorization": f"Bearer {token}",
"Idempotency-Key": idempotency_key, # reutilizada em cada retry
},
json=body,
timeout=30,
).raise_for_status().json()
except httpx.HTTPError:
if attempt == max_attempts - 1:
raise
time.sleep(2 ** attempt)