Controle a parada, as novas tentativas e a recuperação
Limite o ciclo, detecte quando ele está preso, tente de novo com segurança usando backoff e idempotência, e devolva o controle de forma clara.
- Definir orçamentos de etapas e detectar ciclos presos
- Tentar de novo falhas passageiras com backoff exponencial e jitter
- Tornar seguras para repetir as ações com efeitos colaterais, usando chaves de idempotência
Todo ciclo precisa responder a três perguntas: Como sabemos que terminamos? Quando desistimos? O que acontece depois de uma falha?
- Orçamentos - máximo de etapas, de tempo e de gasto. Atingir um deles não é uma pane: salve o progresso e devolva um resumo claro.
- Detecção de travamento - a mesma ação dando o mesmo resultado de novo e de novo significa que o agente não está avançando.
- Conclusão verificada - pare com base na verdade do ambiente (os testes passam), não no modelo dizendo “pronto”.
Experimente
Até 15 XPSimulador de ciclos
Reproduza duas execuções roteirizadas. “Corrigir o bug” dá certo sozinha. “Lançar a correção instável” fica presa - e depois pula o teste e faz o deploy. Rode-a sem controles e depois experimente um orçamento de 4 etapas, a detecção de travamento e o portão de aprovação. Que controle pega o quê?
Objetivo: Fazer a suíte de testes passar.
- 1leiturarun_tests()Pensamento: Ver o que falha primeiro.→ 2 failing: test_total, test_discount
- 2leituraread_file("cart.py")Pensamento: Os dois envolvem descontos - ler o código do carrinho.→ discount applied twice on line 42
- 3escritaedit_file("cart.py", line=42)Pensamento: Remover a segunda aplicação.→ edit applied
- 4leiturarun_tests()Pensamento: Verificar com os testes, não com a minha própria afirmação.→ all 42 tests pass
Novas tentativas do jeito certo
Tente de novo só as falhas que podem ser passageiras (timeouts, limites de taxa, 503) - não um 400 “argumento inválido”. Espere mais a cada vez com backoff exponencial (0,5 s, 1 s, 2 s, 4 s… até um teto) e acrescente jitter - uma espera aleatória entre 0 e o backoff -, para que muitos clientes não tentem de novo ao mesmo tempo (AWS Architecture Blog).
Tentar de novo uma ação com efeitos colaterais é perigoso: um timeout não significa que ela falhou - o pagamento pode ter sido feito e só a resposta se perdeu. Mande uma chave de idempotência com a requisição; o servidor executa a ação uma vez por chave e devolve o resultado original para as duplicatas (a API da Stripe funciona assim).
base, cap = 0.5, 8
print([min(cap, base * 2 ** attempt) for attempt in range(6)])[0.5, 1.0, 2.0, 4.0, 8, 8]
Principais conclusões
Limite as etapas, o tempo e o gasto; pare com um sucesso verificado ou com uma devolução clara do controle.
Detecte ciclos presos - ações repetidas com resultados repetidos.
Tente de novo só os erros passageiros, com backoff exponencial limitado e jitter; use chaves de idempotência para efeitos colaterais.
Quiz da aula
6 perguntas · aprovação com 5 acertos · até 50 XP
Ao passar, você conclui a aula e mantém sua sequência. As perguntas erradas voltarão em sessões de revisão.
Pratique: escreva código em Python
Escreva código Python no editor e execute os testes com exemplos. O Python roda localmente no navegador usando WebAssembly.
Backoff exponencial com jitter completo
Entrada: ATTEMPTS BASE CAP. Chame random.seed(42) uma vez. Para cada tentativa a partir de 0, o backoff é min(CAP, BASE * 2 ** attempt) e a espera real é random.uniform(0, backoff). Imprima attempt N: backoff B s, wait W s, com B formatado com :g e W com 2 casas decimais, numerando as tentativas a partir de 1.
- Seis tentativas
O Python é executado em um ambiente isolado no navegador, com limite de 60 segundos. O runtime é carregado pelo CDN do Pyodide; seu código permanece neste navegador.
Detecte um ciclo preso
Cada linha é action|result. Pare assim que a mesma ação tiver produzido o mesmo resultado 3 vezes e imprima stuck at step N: ACTION keeps returning RESULT. Se isso nunca acontecer, imprima finished after N steps.
- Preso
- Avançando
O Python é executado em um ambiente isolado no navegador, com limite de 60 segundos. O runtime é carregado pelo CDN do Pyodide; seu código permanece neste navegador.
Chaves de idempotência para novas tentativas seguras
Cada linha é KEY AMOUNT, um pedido de pagamento (as novas tentativas reaproveitam a chave). Imprima charged KEY AMOUNT na primeira vez que uma chave aparecer, replayed KEY (no new charge) para uma repetição com o mesmo valor e error: KEY reused with a different amount caso contrário. Termine com total charged: T.
- Um timeout tentado de novo
O Python é executado em um ambiente isolado no navegador, com limite de 60 segundos. O runtime é carregado pelo CDN do Pyodide; seu código permanece neste navegador.
Dúvidas sobre esta lição
Travou em algum ponto? Pergunte. Descobriu algo? Compartilhe. Explicar também é uma ótima forma de aprender.
Carregando publicações…