Carregando
0x40Lição 5 de 8

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.

25 min Questionário com 6 perguntas 3 exercícios de código
Ao final desta lição, você saberá
  • 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 XP

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

  1. 1leiturarun_tests()
    Pensamento: Ver o que falha primeiro.→ 2 failing: test_total, test_discount
  2. 2leituraread_file("cart.py")
    Pensamento: Os dois envolvem descontos - ler o código do carrinho.→ discount applied twice on line 42
  3. 3escritaedit_file("cart.py", line=42)
    Pensamento: Remover a segunda aplicação.→ edit applied
  4. 4leiturarun_tests()
    Pensamento: Verificar com os testes, não com a minha própria afirmação.→ all 42 tests pass
Objetivo atingido: o loop parou em um sucesso verificado.

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

backoff.py
base, cap = 0.5, 8
print([min(cap, base * 2 ** attempt) for attempt in range(6)])
Saída
[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.

Exercício 1

Backoff exponencial com jitter completo

+25 XP

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
main.py
Carregando editor…

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.

Exercício 2

Detecte um ciclo preso

+25 XP

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
main.py
Carregando editor…

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.

Exercício 3

Chaves de idempotência para novas tentativas seguras

+25 XP

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
main.py
Carregando editor…

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…