[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-21-architecture-evenementielle-rust-bus":3},{"article":4,"author":55},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":35,"related_articles":36},"d6000000-0000-0000-0000-000000000121","a0000000-0000-0000-0000-000000000066","Deep EVM #21 : Architecture événementielle en Rust — Pattern Bus pour systèmes temps réel","deep-evm-21-architecture-evenementielle-rust-bus","Concevez un système événementiel en Rust utilisant les channels tokio avec le pattern bus. Couvre mpsc, broadcast et watch avec contrepression et stratégies de fan-out.","## Pourquoi l'architecture événementielle ?\n\nDans les systèmes haute performance comme les bots MEV, les indexeurs blockchain et les moteurs de trading en temps réel, les composants doivent réagir aux événements avec une latence minimale. Le modèle requête-réponse traditionnel ne peut pas suivre. Vous avez besoin d'une architecture événementielle où les composants communiquent par passage de messages asynchrone.\n\n## Les channels tokio\n\nTokio fournit trois types de channels :\n\n### mpsc (Multi-Producer, Single-Consumer)\n\n```rust\nuse tokio::sync::mpsc;\n\nlet (tx, mut rx) = mpsc::channel::\u003CEvent>(1024);\n\n\u002F\u002F Producteur\ntokio::spawn(async move {\n    tx.send(Event::NewBlock(block)).await.unwrap();\n});\n\n\u002F\u002F Consommateur\ntokio::spawn(async move {\n    while let Some(event) = rx.recv().await {\n        process(event).await;\n    }\n});\n```\n\nIdéal pour : pipelines unidirectionnels, files de tâches, agrégation de données.\n\n### broadcast (Multi-Producer, Multi-Consumer)\n\n```rust\nuse tokio::sync::broadcast;\n\nlet (tx, _) = broadcast::channel::\u003CEvent>(1024);\n\n\u002F\u002F Chaque consommateur obtient sa propre copie\nlet mut rx1 = tx.subscribe();\nlet mut rx2 = tx.subscribe();\n\ntokio::spawn(async move {\n    while let Ok(event) = rx1.recv().await {\n        handle_logging(event).await;\n    }\n});\n\ntokio::spawn(async move {\n    while let Ok(event) = rx2.recv().await {\n        handle_strategy(event).await;\n    }\n});\n```\n\nIdéal pour : diffusion d'événements à plusieurs consommateurs (logging, métriques, stratégies).\n\n### watch (Single-Producer, Multi-Consumer, dernier-état)\n\n```rust\nuse tokio::sync::watch;\n\nlet (tx, rx) = watch::channel(State::default());\n\n\u002F\u002F Le producteur met à jour l'état\ntx.send(new_state).unwrap();\n\n\u002F\u002F Les consommateurs lisent le dernier état\nlet current = rx.borrow().clone();\n```\n\nIdéal pour : état partagé qui change fréquemment (prix courant, dernier bloc).\n\n## Le pattern Bus\n\nUn bus d'événements centralise le routage des messages :\n\n```rust\nstruct EventBus {\n    block_tx: broadcast::Sender\u003CBlock>,\n    mempool_tx: broadcast::Sender\u003CTransaction>,\n    opportunity_tx: mpsc::Sender\u003COpportunity>,\n}\n\nimpl EventBus {\n    fn new() -> Self {\n        let (block_tx, _) = broadcast::channel(256);\n        let (mempool_tx, _) = broadcast::channel(4096);\n        let (opportunity_tx, _) = mpsc::channel(1024);\n        Self { block_tx, mempool_tx, opportunity_tx }\n    }\n\n    fn subscribe_blocks(&self) -> broadcast::Receiver\u003CBlock> {\n        self.block_tx.subscribe()\n    }\n}\n```\n\n## Contrepression (Backpressure)\n\nQuand un consommateur est plus lent que le producteur, les messages s'accumulent. Stratégies :\n\n1. **Channel borné** — `mpsc::channel(1024)` bloque le producteur quand le buffer est plein\n2. **try_send** — Écarter les messages si le channel est plein (acceptable pour les métriques)\n3. **Sémaphore** — Limiter le nombre de tâches concurrentes\n\n```rust\nlet semaphore = Arc::new(Semaphore::new(100));\n\nfor event in events {\n    let permit = semaphore.clone().acquire_owned().await.unwrap();\n    tokio::spawn(async move {\n        process(event).await;\n        drop(permit);\n    });\n}\n```\n\n## Conclusion\n\nL'architecture événementielle avec tokio channels est la base des systèmes temps réel en Rust. Le pattern bus centralise le routage, les différents types de channels répondent à différents besoins, et la contrepression garantit la stabilité sous charge.","\u003Ch2 id=\"pourquoi-l-architecture-v-nementielle\">Pourquoi l’architecture événementielle ?\u003C\u002Fh2>\n\u003Cp>Dans les systèmes haute performance comme les bots MEV, les indexeurs blockchain et les moteurs de trading en temps réel, les composants doivent réagir aux événements avec une latence minimale. Le modèle requête-réponse traditionnel ne peut pas suivre. Vous avez besoin d’une architecture événementielle où les composants communiquent par passage de messages asynchrone.\u003C\u002Fp>\n\u003Ch2 id=\"les-channels-tokio\">Les channels tokio\u003C\u002Fh2>\n\u003Cp>Tokio fournit trois types de channels :\u003C\u002Fp>\n\u003Ch3>mpsc (Multi-Producer, Single-Consumer)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-rust\">use tokio::sync::mpsc;\n\nlet (tx, mut rx) = mpsc::channel::&lt;Event&gt;(1024);\n\n\u002F\u002F Producteur\ntokio::spawn(async move {\n    tx.send(Event::NewBlock(block)).await.unwrap();\n});\n\n\u002F\u002F Consommateur\ntokio::spawn(async move {\n    while let Some(event) = rx.recv().await {\n        process(event).await;\n    }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Idéal pour : pipelines unidirectionnels, files de tâches, agrégation de données.\u003C\u002Fp>\n\u003Ch3>broadcast (Multi-Producer, Multi-Consumer)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-rust\">use tokio::sync::broadcast;\n\nlet (tx, _) = broadcast::channel::&lt;Event&gt;(1024);\n\n\u002F\u002F Chaque consommateur obtient sa propre copie\nlet mut rx1 = tx.subscribe();\nlet mut rx2 = tx.subscribe();\n\ntokio::spawn(async move {\n    while let Ok(event) = rx1.recv().await {\n        handle_logging(event).await;\n    }\n});\n\ntokio::spawn(async move {\n    while let Ok(event) = rx2.recv().await {\n        handle_strategy(event).await;\n    }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Idéal pour : diffusion d’événements à plusieurs consommateurs (logging, métriques, stratégies).\u003C\u002Fp>\n\u003Ch3>watch (Single-Producer, Multi-Consumer, dernier-état)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-rust\">use tokio::sync::watch;\n\nlet (tx, rx) = watch::channel(State::default());\n\n\u002F\u002F Le producteur met à jour l'état\ntx.send(new_state).unwrap();\n\n\u002F\u002F Les consommateurs lisent le dernier état\nlet current = rx.borrow().clone();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Idéal pour : état partagé qui change fréquemment (prix courant, dernier bloc).\u003C\u002Fp>\n\u003Ch2 id=\"le-pattern-bus\">Le pattern Bus\u003C\u002Fh2>\n\u003Cp>Un bus d’événements centralise le routage des messages :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">struct EventBus {\n    block_tx: broadcast::Sender&lt;Block&gt;,\n    mempool_tx: broadcast::Sender&lt;Transaction&gt;,\n    opportunity_tx: mpsc::Sender&lt;Opportunity&gt;,\n}\n\nimpl EventBus {\n    fn new() -&gt; Self {\n        let (block_tx, _) = broadcast::channel(256);\n        let (mempool_tx, _) = broadcast::channel(4096);\n        let (opportunity_tx, _) = mpsc::channel(1024);\n        Self { block_tx, mempool_tx, opportunity_tx }\n    }\n\n    fn subscribe_blocks(&amp;self) -&gt; broadcast::Receiver&lt;Block&gt; {\n        self.block_tx.subscribe()\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"contrepression-backpressure\">Contrepression (Backpressure)\u003C\u002Fh2>\n\u003Cp>Quand un consommateur est plus lent que le producteur, les messages s’accumulent. Stratégies :\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Channel borné\u003C\u002Fstrong> — \u003Ccode>mpsc::channel(1024)\u003C\u002Fcode> bloque le producteur quand le buffer est plein\u003C\u002Fli>\n\u003Cli>\u003Cstrong>try_send\u003C\u002Fstrong> — Écarter les messages si le channel est plein (acceptable pour les métriques)\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Sémaphore\u003C\u002Fstrong> — Limiter le nombre de tâches concurrentes\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cpre>\u003Ccode class=\"language-rust\">let semaphore = Arc::new(Semaphore::new(100));\n\nfor event in events {\n    let permit = semaphore.clone().acquire_owned().await.unwrap();\n    tokio::spawn(async move {\n        process(event).await;\n        drop(permit);\n    });\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C\u002Fh2>\n\u003Cp>L’architecture événementielle avec tokio channels est la base des systèmes temps réel en Rust. Le pattern bus centralise le routage, les différents types de channels répondent à différents besoins, et la contrepression garantit la stabilité sous charge.\u003C\u002Fp>\n","fr","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:29.321642Z","Architecture événementielle en Rust — Pattern Bus pour systèmes temps réel","Systèmes événementiels en Rust avec tokio channels : mpsc, broadcast et watch pour des performances temps réel.","architecture événementielle rust tokio",null,"index, follow",[22,27,31],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000022","Performance","performance",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000001","Rust","rust","Ingénierie",[37,43,49],{"id":38,"title":39,"slug":40,"excerpt":41,"locale":12,"category_name":35,"published_at":42},"d0000000-0000-0000-0000-000000000677","Pourquoi Bali devient le hub impact-tech d'Asie du Sud-Est en 2026","pourquoi-bali-devient-hub-impact-tech-asie-sud-est-2026","Bali se classe 16e parmi les écosystèmes startups d'Asie du Sud-Est. Avec une concentration croissante de bâtisseurs Web3, de startups IA durables et d'entreprises eco-travel tech, l'île se forge une identité de capitale impact-tech de la région.","2026-03-28T10:44:49.517126Z",{"id":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":35,"published_at":48},"d0000000-0000-0000-0000-000000000676","Le patchwork de la protection des données ASEAN : checklist de conformité pour les développeurs","patchwork-protection-donnees-asean-checklist-conformite-developpeurs","Sept pays de l'ASEAN disposent désormais de lois complètes sur la protection des données, chacune avec des modèles de consentement, des exigences de localisation et des structures de sanctions différents. Voici une checklist pratique de conformité pour les développeurs.","2026-03-28T10:44:49.504560Z",{"id":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":35,"published_at":54},"d0000000-0000-0000-0000-000000000675","La transformation numérique de 29 milliards de dollars d'Indonesia : opportunités pour les éditeurs de logiciels","transformation-numerique-29-milliards-dollars-indonesia-opportunites-editeurs-logiciels","Le marché des services informatiques d'Indonesia devrait atteindre 29,03 milliards de dollars en 2026, contre 24,37 milliards en 2025. L'infrastructure cloud, l'IA, le e-commerce et les centres de données tirent la croissance la plus rapide d'Asie du Sud-Est.","2026-03-28T10:44:49.469231Z",{"id":13,"name":56,"slug":57,"bio":58,"photo_url":19,"linkedin":19,"role":59,"created_at":60,"updated_at":60},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]