AULA 35 / 61 · ACESSO GRATUITO

Erros e estados de falha

Graciliano TolentinoEngenharia Caracol · Edição 2.0
Nesta aula
  1. Falhar não deve criar um resultado falso
  2. Resposta pública e diagnóstico
  3. Uma resposta perdida não significa ausência de efeito
  4. Teste que simula a perda da resposta
  5. Procedimento para repetição segura
  6. Condição de avanço e exercício resolvido
  7. Leitura técnica relacionada

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.

Três chamadas: pedido-001 com c01 cria R1 e um efeito; repetir a mesma chave e caso retorna R1 sem novo efeito; reutilizar a chave com c02 causa conflito HTTP409 e mantém um efeito.Ampliar diagrama
Repetir a solicitação não repete o efeito. Os casos c01 e c02 são públicos e válidos neste cenário. Idempotência usa a identidade da operação, não apenas o fato de a tela parecer igual. O contrato da oficina conserva estado em memória e não garante reserva durável.

Resposta pública e diagnóstico

CondiçãoResposta esperada na APIAção
Solicitação de reserva malformada400Corrigir a entrada; não repetir a mesma solicitação inválida.
Caso não público404Não reservar caso ausente ou inativo.
Mesma chave com outro caso409Tratar o conflito de intenção; não criar chave nova automaticamente para esconder o erro.
Dado do catálogo inválido ou falha inesperada500 com mensagem genéricaRegistrar 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.

javascript
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 S19
Conseguiu explicar o que aprendeu?

Tente 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.