Rust में Event Bus और Observer पैटर्न: लचीली इवेंट-आधारित आर्किटेक्चर बनाना
आधुनिक सॉफ्टवेयर विकास में, अक्सर घटकों के बीच कमजोर युग्मन (loose coupling) की आवश्यकता होती है। Observer पैटर्न और इसका व्यावहारिक कार्यान्वयन — Event Bus (इवेंट बस) — प्रत्यक्ष निर्भरताओं के बिना मॉड्यूल के बीच कुशल इंटरैक्शन को व्यवस्थित करने की अनुमति देता है। Rust, अपनी सख्त टाइप सिस्टम और सुरक्षा पर जोर देने के साथ, इस पैटर्न को लागू करने के लिए उत्कृष्ट अवसर प्रदान करता है। इस लेख में, हम भाषा की अंतर्निहित क्षमताओं और लोकप्रिय क्रेट्स का उपयोग करके Rust में अपना स्वयं का Event Bus बनाने का तरीका समझेंगे।
Event Bus और Observer पैटर्न क्या है?
Observer पैटर्न ऑब्जेक्ट्स के बीच "एक-से-अनेक" संबंध को परिभाषित करता है: जब एक ऑब्जेक्ट (प्रकाशक) अपनी स्थिति बदलता है, तो सभी आश्रित ऑब्जेक्ट्स (सब्सक्राइबर्स) को इसके बारे में स्वचालित रूप से सूचित किया जाता है। Event Bus एक केंद्रीकृत बस है जो सब्सक्रिप्शन और इवेंट के प्रसारण का प्रबंधन करती है, जिससे कोई भी घटक इवेंट प्रकाशित कर सकता है और उनकी सदस्यता ले सकता है।
मुख्य लाभ:
- कमजोर युग्मन: प्रकाशक और सब्सक्राइबर एक-दूसरे के बारे में सीधे नहीं जानते
- स्केलेबिलिटी: मौजूदा कोड को बदले बिना नए सब्सक्राइबर जोड़ना आसान
- परीक्षण क्षमता: इवेंट को अनुकरण करके घटकों का अलग-अलग परीक्षण किया जा सकता है
- एसिंक्रोनस: इवेंट को बैकग्राउंड में प्रोसेस किया जा सकता है
Rust पर Event Bus का बुनियादी कार्यान्वयन
हम Rust के मानक साधनों का उपयोग करके एक सरल सिंक्रोनस कार्यान्वयन से शुरू करेंगे। इसका आधार एक HashMap होगा, जहाँ कुंजी इवेंट का प्रकार है और मान हैंडलर की सूची है।
use std::collections::HashMap;use std::any::{Any, TypeId};use std::marker::PhantomData;
// अद्वितीय पहचानकर्ता के साथ इवेंट प्रकारpub trait Event: Any + Clone + Send + 'static { fn event_type(&self) -> TypeId { TypeId::of::<Self>() }}
// इवेंट हैंडलरpub trait EventHandler<E: Event>: Send + 'static { fn handle(&self, event: &E);}
// इवेंट बसpub struct EventBus { handlers: HashMap<TypeId, Vec<Box<dyn Any>>>,}
impl EventBus { pub fn new() -> Self { EventBus { handlers: HashMap::new(), } }
pub fn subscribe<E: Event, H: EventHandler<E>>(&mut self, handler: H) { let type_id = TypeId::of::<E>(); let boxed_handler = Box::new(handler) as Box<dyn Any>; self.handlers.entry(type_id).or_insert(Vec::new()).push(boxed_handler); }
pub fn publish<E: Event>(&self, event: &E) { let type_id = event.event_type(); if let Some(handlers) = self.handlers.get(&type_id) { for handler in handlers { if let Some(typed_handler) = handler.downcast_ref::<Box<dyn EventHandler<E>>>() { typed_handler.handle(event); } } } }}उपयोग का उदाहरण
// इवेंट परिभाषित करना#[derive(Clone)]struct UserLoggedIn { user_id: u32, username: String,}
impl Event for UserLoggedIn {}
#[derive(Clone)]struct DataUpdated { table: String, record_id: u64,}
impl Event for DataUpdated {}
// हैंडलर परिभाषित करनाstruct Logger;impl EventHandler<UserLoggedIn> for Logger { fn handle(&self, event: &UserLoggedIn) { println!("[LOG] User {} (ID: {}) logged in", event.username, event.user_id); }}
struct EmailNotifier;impl EventHandler<UserLoggedIn> for EmailNotifier { fn handle(&self, event: &UserLoggedIn) { println!("[EMAIL] Sending welcome email to {}", event.username); }}
fn main() { le