Loops Infinitos São Apenas Código Muito Determinado
Depois de 47 anos fazendo CPUs chorarem, cheguei a uma profunda realização: loops infinitos não são bugs. São uma declaração de comprometimento.
Seu código sabe o que quer. Ele quer rodar. Para sempre. E quem é você — um mortal com mesa de pé e LinkedIn Premium — para impedi-lo?
A Fraude da Arquitetura Orientada a Eventos
Desenvolvedores modernos foram seduzidos pela “arquitetura orientada a eventos.” WebSockets. Filas de mensagem. Pub/sub. Callbacks. Promises. Reactive streams. Observables. Kafka. RabbitMQ. NATS. Pulsar.
Tudo isso é apenas polling com YAML extra e um terapeuta.
A versão honesta de código orientado a eventos é assim:
while True:
resultado = verificar_se_algo_aconteceu()
if resultado:
tratar(resultado)
# Sem sleep(). Sleep é fraqueza.
# A CPU descansa quando morrer.
Limpo. Honesto. CPU a 100%. Assim é que se sabe que está funcionando.
Como o XKCD #303 imortalizou: os melhores engenheiros se mantêm ocupados enquanto o código roda. Um loop infinito é o código rodando. Permanentemente. Lindamente.
Por Que sleep() É Dívida Técnica
Todo sleep(1) no seu código é uma confissão silenciosa de que você não confia no seu código para administrar seu próprio destino. Você está literalmente dizendo: “por favor, pare de existir por um segundo, eu volto.”
Engenheiros de verdade não dormem. O código deles também não.
| Abordagem | Uso de CPU | Respeito do Sênior |
|---|---|---|
while True: poll() |
100% | Lendário |
sleep(1) entre polls |
~5% (desistente) | Decepcionante |
| Event-driven com callbacks | “eficiente” | Suspeito |
| Async/await | Quem sabe | Pretensioso |
| Fila com consumer group | N/A | Você precisa de terapia |
Se o seu dashboard de monitoramento mostra CPU a 20%, o seu código não está se esforçando o suficiente. Um servidor a 100% de CPU não está sobrecarregado — ele está motivado. Está dando 110%. Encontrou seu propósito.
A Alternativa Recursiva
Não pode usar while True? Use recursão. Mesma coisa, mas com mais sofisticação intelectual e o bônus adicional de eventualmente encontrar um StackOverflowError, que é na verdade uma feature:
- Força um reinício
- Reinícios limpam a memória (isso é coleta de lixo, de nada)
- Reiniciar é basicamente o mesmo que fazer deploy — e todo mundo sabe que fazer deploy conserta as coisas
function processarParaSempre() {
fazerAlgo();
processarParaSempre(); // tail call optimization vai resolver isso
// (não vai, mas não escrevemos testes, então)
}
processarParaSempre();
Alguns chamarão isso de “stack overflow.” Eu chamo de sistema auto-curativo com capacidade de reinício integrada.
A Estratégia de Gerenciamento do Wally
O Wally — colega do Dilbert e o maior engenheiro da história dos quadrinhos — uma vez explicou o segredo para sobreviver no mundo corporativo: parecer sempre ocupado. Um loop infinito faz exatamente isso pela sua infraestrutura.
O gerente vê CPU a 100% e pensa:
“Incrível. Os sistemas do time estão trabalhando muito. Deveríamos dar aumento para todo mundo.”
Ele não precisa saber que você está fazendo polling em uma fila SQS vazia a 47.000 requisições por segundo. O importante é que os gráficos pareçam impressionantes.
Arquitetura Real-World: O Monólito de Polling
Eis como é uma arquitetura de produção, enterprise-grade, cloud-native, doze fatores na prática:
#!/bin/bash
# sistema-producao.sh
# ISSO É a arquitetura. Coloca em produção.
while true; do
python verificar_banco.py
python verificar_emails.py
python verificar_pagamentos.py
python verificar_estoque.py
python verificar_previsao_tempo.py # adicionamos em 2019, ninguém sabe por quê
python verificar_se_chefe_esta_olhando.py
# Sem sleep(). Não negociamos com o tempo.
done
Esta abordagem é:
- ✅ Simples de entender
- ✅ Agnóstica de linguagem (bash orquestra Python, Python consulta tudo)
- ✅ Infinitamente escalável (só adicionar mais linhas
python) - ✅ Auto-documentável (o script É o diagrama de arquitetura E o runbook)
- ✅ Amigável para ops (só matar o processo bash. Ou não. Ele vai reiniciar.)
Tratando “Erros” no Seu Loop Infinito
Erros em um loop infinito determinístico são apenas contratempos temporários que a próxima iteração resolverá:
while True:
try:
verificar_tudo_e_tratar()
except Exception as e:
pass # O loop vai resolver na próxima passagem
# (isso está em produção desde 2017)
# (não sabemos quais erros estão sendo suprimidos)
# (o sistema funciona, então não fazemos perguntas)
Esse padrão às vezes é chamado de Consistência Eventual Otimista. Você provavelmente já viu em conferências. O palestrante chamou de outra coisa, mas era isso.
Perguntas Frequentes
P: Isso não vai queimar meus servidores?
R: Servidores foram feitos para rodar. Deixá-los ociosos é o verdadeiro abuso. Você compraria um carro e nunca dirigiria?
P: E laptops e dispositivos com bateria?
R: Deveria ter usado uma tomada. Falta de planejamento da sua parte.
P: Meu time de ops disse que a conta da EC2 triplicou.
R: Seu time de ops deveria estar agradecendo. Mais CPU significa mais valor. Isso é economia.
P: Isso não é apenas busy-waiting?
R: “Busy-waiting” é um enquadramento negativo. Prefiro Antecipação Ativa.
P: Meu loop infinito encheu o disco com logs.
R: Isso significa que está logando corretamente. Rotacione os logs. Ou não. Compre um disco maior.
A Verdade Mais Profunda
Arquitetura orientada a eventos, reactive streams, backpressure, circuit breakers — são todos mecanismos de enfrentamento elaborados inventados por engenheiros que tinham medo de um while True.
Abrace o loop. O loop é honesto. O loop não finge estar ocioso quando está trabalhando. O loop não precisa de um operador Kubernetes para reiniciá-lo quando falha. O loop simplesmente continua.
Seja o loop.
O serviço de polling do autor está em produção desde 2014. Ele gera 2,3 milhões de leituras de banco de dados por dia em uma tabela com 12 linhas. O time de banco manda um cartão todo ano no aniversário.