← REST APIs: integrar aplicações e diagnosticar falhas
07 / 12 · 60 MIN

Recuperar pedidos sem duplicar trabalho

Distingue tentativa, operação e resultado; decide quando consultar, repetir ou escalar.

1. Um timeout deixa uma pergunta em aberto

Um pedido percorre várias fronteiras: cliente, intermediário, aplicação e persistência. Se a resposta se perder depois da criação de um job, o cliente conhece uma falha de comunicação, mas não o resultado do serviço. No laboratório, o servidor cria um pedido de geração de relatório e fecha deliberadamente a ligação antes de responder. O cliente recebe RemoteDisconnected. Essa observação deve manter o estado como desconhecido até existir evidência adicional. Não marques o job como falhado nem como concluído apenas a partir da exceção. Durante suporte L3, regista a referência da operação, a janela temporal e a camada onde a comunicação terminou.

2. A identidade pertence à intenção

Uma tentativa é um envio; uma operação é a intenção que esse envio procura realizar. A chave de idempotência permite ao contrato relacionar várias tentativas com a mesma intenção. No fixture, a identidade inclui tenant, endpoint e chave. Repetir a mesma combinação e o mesmo payload devolve a aceitação guardada sem criar outro job. Alterar o payload com a chave ainda válida recebe 409. Este comportamento é uma escolha explícita do laboratório. A documentação Stripe mostra um contrato real com retenção e comparação de parâmetros, mas não transforma todos os POST de todos os fornecedores em operações idempotentes.

3. Âmbito, acesso e expiração

O serviço deve verificar o acesso atual antes de entregar uma resposta guardada. Um utilizador pode perder autorização depois do primeiro pedido; conhecer a chave não recupera esse acesso. Dois tenants distintos podem usar o mesmo texto de chave sem partilhar resultados quando o namespace inclui o tenant autenticado. O laboratório simula esse contexto com headers X-Lab; estes headers são seletores de teste, não autenticação utilizável. A retenção também limita a garantia. Após dez ticks sintéticos, o fixture esquece a chave, mas conserva o job. Repetir então pode criar outro job. Os dez ticks são uma escolha didática, não uma regra HTTP ou de um fornecedor.

4. Aceitação guardada e estado atual

Uma resposta 202 pode apontar para um recurso onde o consumidor acompanha o trabalho. No exercício, o POST guarda id e state=queued. O runner altera depois o estado do job para succeeded, simulando a conclusão de um worker. Um GET mostra o estado atual, enquanto o replay do POST continua a devolver a aceitação inicial. Não interpretes esse replay como regressão à fila. Acompanha a identidade do job e consulta o recurso apropriado segundo o contrato. No trabalho, distingue o indicador de disponibilidade da API, a taxa de aceitação e a conclusão funcional do processo que o negócio espera.

5. Um orçamento para todas as tentativas

Uma política de recuperação precisa de limites de tentativas, tempo total e autoridade para reenvio. No exemplo guiado, restam 1,5 segundos e a resposta pede uma espera de dois segundos. A política fornecida exige respeitar a espera e proíbe iniciar depois do prazo; portanto, encaminha para a recuperação prevista sem iniciar novo pedido. Considera também as camadas: três tentativas totais do cliente, cada uma com três do gateway, podem produzir nove pedidos ao serviço. Contabiliza o retry onde ele realmente ocorre. Uma melhoria local de resiliência pode aumentar carga e atrasar outros consumidores se não houver coordenação.

6. Exercício de suporte e passagem de turno

Analisa o caso de uma resposta perdida cuja chave já expirou. Prepara uma passagem de turno com a referência de negócio, o resultado conhecido ou desconhecido, a última consulta autorizada, a janela de retenção e o responsável pela decisão de reenvio. Se a consulta confirmar um job concluído, valida o resultado esperado; se mostrar falha, aplica o procedimento aprovado; se permanecer ambígua, mantém a ambiguidade explícita. O laboratório executa HTTP real apenas em loopback e estado em memória. Não ensaia APIs bancárias, efeitos financeiros, TLS, persistência após reinício nem recuperação entre regiões.

# Observações do fixture local, com dados sintéticos
POST /jobs  Idempotency-Key: lost  -> ligação fechada após criar job 1
POST /jobs  Idempotency-Key: lost  -> 202 {"id":"1","state":"queued"}
GET /jobs/1                      -> 200 {"id":"1","state":"succeeded"}
# O POST repetido conserva a resposta inicial; GET mostra o estado atual.
NA PRÁTICA

POST cria job 1, a resposta perde-se, e o retry com a mesma identidade devolve job 1. A contagem continua em um; após expiração da chave, outro envio cria job 3 no ensaio.

Armadilhas comuns

Trocar a chave em cada retry; confundir 202 com conclusão; ignorar retenção; tratar headers de teste como autenticação.

Tópicos relacionados: HTTP e HTTPS · Controlo de concorrência · Observabilidade e recuperação

Leva esta ideia contigo

Recupera a intenção original com identidade, consulta e limites explícitos; não deduzas o resultado apenas do transporte.

Criar conta

Referência: Idempotent requests · HTTP semantics RFC9110; OpenAPI3.2.1; selected primary standards and provider contracts consulted2026-09-30