Quando os eventos controlam o código: Event-driven em Rust
\n\nImagine que seu código é um maestro de orquestra. Na programação síncrona clássica, o maestro decide quando cada nota deve soar. Na arquitetura orientada a eventos, o maestro apenas reage ao fato de que os músicos já começaram a tocar. Parece paradoxal? Só à primeira vista.
\n\nArquitetura orientada a eventos (event-driven) é uma abordagem onde o fluxo de execução do programa é determinado por eventos: clique do mouse, recebimento de uma requisição HTTP, conclusão de E/S, temporizador. Rust, com seu sistema de ownership e abstrações de custo zero, é o terreno ideal para essa arquitetura. Especialmente se você vem do Python, onde o event loop (por exemplo, no asyncio) funciona, mas frequentemente esbarra no GIL e na sobrecarga da tipagem dinâmica.
\n\nNeste artigo, não vamos apenas falar sobre teoria. Vamos escrever código real, analisar a arquitetura orientada a eventos em Rust usando crates populares e mostrar como isso pode acelerar suas aplicações significativamente.
\n\nPor que Rust, e não Python, para eventos?
\n\nPython é uma excelente linguagem para prototipagem. Mas quando você precisa de processamento de eventos em tempo real com milhares de conexões simultâneas, Python começa a ficar lento. Rust oferece:
\n\n- \n
- Abstrações de custo zero — async/await não adiciona overhead se você não usar seus recursos \n
- Ausência de coletor de lixo — sem pausas repentinas ao processar eventos \
- Sistema de tipos que captura erros em tempo de compilação \n
- Paralelismo real — não é multitarefa cooperativa, mas threads reais sem GIL \n
Se você escreve aplicações orientadas a eventos em Rust, obtém controle sobre cada byte de memória e cada ciclo de CPU. E isso não é marketing — é um fato.
\n\nFundamentos: Event Loop e processamento de eventos
\n\nNa base de qualquer sistema orientado a eventos está o event loop (laço de eventos). É um loop infinito que:
\n\n- \n
- Aguarda o surgimento de um novo evento \n
- Extrai-o da fila \n
- Passa para o manipulador \n
- Repete \n
Em Rust, o event loop padrão é fornecido pela crate tokio. Vamos escrever um exemplo simples:
use tokio::sync::mpsc;\nuse tokio::time::{sleep, Duration};\n\n#[tokio::main]\nasync fn main() {\n // Cria um canal para transmitir eventos\n let (tx, mut rx) = mpsc::channel::<String>(32);\n\n // Produtor: gera eventos\n tokio::spawn(async move {\n for i in 0..5 {\n let event = format!("Evento nº{}", i);\n tx.send(event).await.unwrap();\n sleep(Duration::from_millis(500)).await;\n }\n });\n\n // Consumidor: processa eventos\n while let Some(event) = rx.recv().await {\n println!("Processado: {}", event);\n // Sua lógica de negócios pode estar aqui\n }\n}\n\nEste código demonstra o padrão básico de programação orientada a eventos em Rust: um componente gera eventos, outro os processa. O canal mpsc (multi-produtor, único consumidor) garante a transmissão segura de dados entre tarefas.
Exemplo avançado: sistema de processamento de pedidos
\n\nVamos complicar a tarefa. Imagine que estamos escrevendo o backend de uma loja online. Quando um novo pedido chega, precisamos:
\n\n- \n
- Verificar a disponibilidade do produto \n
- Reservá-lo \n
- Enviar uma notificação \n
- Atualizar as estatísticas \n
A abordagem clássica é fazer tudo de forma síncrona. A abordagem orientada a eventos é dividir em eventos:
\n\nuse tokio::sync::broadcast;\nuse tokio::time::sleep;\nuse std::time::Duration;\n\n#[derive(Debug, Clone)]\nenum OrderEvent {\n NewOrder { id: u32, items: Vec<String>