Erros e estados de falha
Nesta aula
Falhar não deve criar um resultado falso
Um catálogo vazio é um resultado válido: o sistema leu dados corretos e não encontrou serviço ativo. Um catálogo indisponível significa que a operação não pôde produzir uma resposta confiável. Misturar os dois estados esconde defeitos. A Oficina deve mostrar carregamento enquanto aguarda, vazio quando a lista válida está vazia e falha quando a leitura ou validação não permite publicar o conjunto.
A validação de JSON envolve pelo menos duas perguntas diferentes. O texto pode ser convertido em um valor? Esse valor respeita o contrato de dados? JSON sintaticamente correto, como {"ativo":"sim"}, ainda pode ser inválido para o catálogo. npm run validate verifica os dados e os testes antes da entrega, mas só bloqueia publicação se o processo de entrega realmente condicionar a publicação à aprovação. O comando não cria sozinho uma política de implantação.
Resposta pública e diagnóstico
| Condição | Resposta esperada na API | Ação |
|---|---|---|
| Solicitação de reserva malformada | 400 | Corrigir a entrada; não repetir a mesma solicitação inválida. |
| Caso não público | 404 | Não reservar caso ausente ou inativo. |
| Mesma chave com outro caso | 409 | Tratar o conflito de intenção; não criar chave nova automaticamente para esconder o erro. |
| Dado do catálogo inválido ou falha inesperada | 500 com mensagem genérica | Registrar diagnóstico técnico apropriado, corrigir a causa e preservar navegação. |
O usuário precisa de uma mensagem útil; o operador precisa do diagnóstico suficiente para investigar. Não coloque credenciais, corpos completos de solicitações sensíveis ou detalhes internos desnecessários na mensagem pública. Se uma credencial real for exposta, reduzir o tamanho da mudança não corrige a exposição: é necessário revogar ou rotacionar a credencial, retirar o valor e tratar cópias conforme o alcance.
Uma resposta perdida não significa ausência de efeito
Timeout significa que o cliente deixou de esperar dentro de um prazo. Não prova que o servidor deixou de executar. Repetir uma operação de escrita sem um acordo pode gerar dois efeitos. A idempotência da reserva simulada usa uma chave para identificar a mesma intenção: repetir a chave com o mesmo caso retorna o mesmo resultado lógico sem criar outra reserva. A chave deve ser conservada na nova tentativa; uma ação nova recebe outra chave.
No contrato do simulador, o estado vive em memória. O efeito único vale para a mesma instância enquanto esse estado existe. Reiniciar o processo apaga o registro; não há garantia de durabilidade, coordenação entre processos ou reservas reais. Em uma aplicação real, a decisão sobre persistência e atomicidade precisa fazer parte da arquitetura.
Teste que simula a perda da resposta
Este teste usa o export real de src/operacoes.mjs e pode ser incluído no conjunto de tests/operacoes.test.mjs. Ele não precisa simular uma rede instável: descartar a primeira resposta já reproduz a dúvida do cliente sobre o resultado.
import test from 'node:test';
import assert from 'node:assert/strict';
import { criarRegistradorDeReservas } from '../src/operacoes.mjs';
test('repetir a mesma intenção mantém um único efeito', () => {
const registrador = criarRegistradorDeReservas();
const pedido = { chave: 'tentativa-001', casoId: 'site-acessivel' };
const primeira = registrador.reservar(pedido);
// O cliente não recebeu a primeira resposta.
const repetida = registrador.reservar(pedido);
assert.deepEqual(repetida, primeira);
assert.equal(registrador.contar(), 1);
assert.throws(
() => registrador.reservar({ ...pedido, casoId: 'catalogo-local' }),
erro => erro.codigo === 'CONFLITO_CHAVE'
);
assert.equal(registrador.contar(), 1);
});A igualdade do resultado verifica o replay; contar igual a um verifica o efeito único. O conflito com outro caso protege a intenção. Nenhuma dessas asserções comprova que o servidor HTTP mapeia o conflito para 409; essa é outra fronteira, coberta no teste do servidor.
Procedimento para repetição segura
- Classifique a falha: erro de validação e conflito de intenção exigem decisão, não repetição automática.
- Confirme se a operação é segura para repetição e se possui contrato idempotente. Sem isso, investigue o resultado anterior antes de tentar novamente.
- Para a mesma reserva, preserve chave e parâmetros. Nunca gere uma chave nova a cada tentativa automática.
- Defina limite de tentativas e prazo total; em serviços externos, considere espera progressiva, variação de intervalo e indicação do serviço.
- Ao esgotar o limite, apresente estado explícito e caminho de recuperação. Registre a falha sem afirmar que nenhum efeito aconteceu.
Condição de avanço e exercício resolvido
Avance quando estados obrigatórios de sucesso, vazio, inválido e falha tiverem respostas verificadas, e quando a reserva demonstrar replay e conflito sem novo efeito no escopo declarado. Um retry infinito ou uma resposta perdida tratada como “reserva não criada” bloqueia a prova correspondente.
Dados do exercício: pedido {chave:"aula-009",casoId:"site-acessivel"}; o servidor aplica a reserva e a resposta se perde. O cliente tenta novamente com chave "aula-010". Depois tenta "aula-009" para "catalogo-local". Identifique os dois erros e a sequência correta.
Ver solução comentada
Resolução: a chave nova transforma a repetição em nova intenção e pode criar outro efeito. A chave antiga com outro caso deve gerar CONFLITO_CHAVE, ou HTTP 409 pela API. A sequência correta repete "aula-009" com "site-acessivel", verifica o resultado lógico e mantém a contagem em um. A rubrica exige distinguir timeout de ausência de efeito, preservar parâmetros e declarar o limite de memória do simulador.
Leitura técnica relacionada
S15: AWS Builders Library, Making retries safe with idempotent APIs, especialmente identificador fornecido pelo cliente, equivalência de resposta e conflito de parâmetros. S18: MDN, try...catch. S19: Node.js, test runner e HTTP. O simulador é uma demonstração limitada, não uma implementação de transação durável.
Fontes relacionadas
Consulte os limites e as seções de apoio de cada referência.
S15 S18 S19Tente o exercício antes de consultar a solução. Marque a aula para organizar sua leitura.
A conclusão desta leitura não equivale a certificação ou aceite de um projeto real. Teste os exemplos no escopo indicado e registre as limitações.