Deep EVM #21: Arquitectura Dirigida por Eventos en Rust — Patrón Bus para Sistemas en Tiempo Real
Engineering Team
El patrón de bus de eventos
En sistemas complejos como bots de MEV o pipelines de datos, los componentes necesitan comunicarse sin acoplamiento directo. El patrón de bus de eventos proporciona esta desvinculación: los productores publican eventos sin saber quién escucha, y los consumidores se suscriben sin saber quién produce.
Implementación con tokio::broadcast
use tokio::sync::broadcast;
#[derive(Clone, Debug)]
enum Event {
NewBlock(BlockData),
NewTransaction(TxData),
ArbitrageFound(ArbOpportunity),
BundleSubmitted(BundleResult),
}
struct EventBus {
sender: broadcast::Sender<Event>,
}
impl EventBus {
fn new(capacity: usize) -> Self {
let (sender, _) = broadcast::channel(capacity);
Self { sender }
}
fn publish(&self, event: Event) {
let _ = self.sender.send(event);
}
fn subscribe(&self) -> broadcast::Receiver<Event> {
self.sender.subscribe()
}
}
Componentes desacoplados
Cada componente del sistema se suscribe solo a los eventos que le interesan:
// Componente: detector de arbitraje
async fn arbitrage_detector(bus: Arc<EventBus>) {
let mut rx = bus.subscribe();
while let Ok(event) = rx.recv().await {
if let Event::NewBlock(block) = event {
let opportunities = find_arbitrage(&block).await;
for opp in opportunities {
bus.publish(Event::ArbitrageFound(opp));
}
}
}
}
// Componente: simulador
async fn simulator(bus: Arc<EventBus>) {
let mut rx = bus.subscribe();
while let Ok(event) = rx.recv().await {
if let Event::ArbitrageFound(opp) = event {
let result = simulate(opp).await;
if result.is_profitable() {
bus.publish(Event::BundleSubmitted(
submit_bundle(result).await
));
}
}
}
}
Ventajas de esta arquitectura
- Desacoplamiento — Los componentes no se conocen entre sí
- Escalabilidad — Añadir nuevos consumidores no afecta a los productores
- Testing — Cada componente se puede testear independientemente
- Resiliencia — Si un consumidor falla, los demás continúan
Manejo de backpressure
Cuando los consumidores no pueden procesar eventos a la velocidad de producción, el canal broadcast descarta mensajes antiguos. Usa canales con capacidad adecuada y monitorea los retrasos.
Conclusión
La arquitectura de bus de eventos con tokio::broadcast es ideal para sistemas Rust en tiempo real. El desacoplamiento entre componentes facilita el desarrollo, testing y mantenimiento de sistemas complejos como bots de MEV y pipelines de datos de blockchain.