Skip to main content

sz_rust_core/plugin/
event_bus.rs

1//! 事件总线 trait + EventHandler trait 抽象。
2//!
3//! 对应 design.md §2.2.2 接口 7-8。
4//! 所有 trait 必须 `Send + Sync + 'static`。
5
6use async_trait::async_trait;
7use serde::{Deserialize, Serialize};
8use std::sync::Arc;
9
10use super::schema::SysEvent;
11
12/// 事件 ID 类型。
13pub type EventId = i64;
14
15/// 订阅 ID 类型。
16pub type SubscriptionId = u64;
17
18/// 插件事件。
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct PluginEvent {
21    /// 事件 ID(发布后分配)
22    pub id: EventId,
23    /// 租户 ID(多租户隔离)
24    pub tenant_id: i64,
25    /// 事件类型(如 order.created)
26    pub event_type: String,
27    /// 来源插件名
28    pub source_plugin: String,
29    /// 事件负载(JSON)
30    pub payload: serde_json::Value,
31}
32
33impl From<SysEvent> for PluginEvent {
34    fn from(e: SysEvent) -> Self {
35        Self {
36            id: e.id,
37            tenant_id: e.tenant_id,
38            event_type: e.event_type,
39            source_plugin: e.source_plugin,
40            payload: e.payload,
41        }
42    }
43}
44
45/// 事件处理器 trait。
46#[async_trait]
47pub trait EventHandler: Send + Sync + 'static {
48    /// 处理事件,返回 `Ok(())` 表示处理成功。
49    async fn handle(&self, event: &PluginEvent) -> Result<(), String>;
50}
51
52/// 事件总线 trait。
53#[async_trait]
54pub trait EventBus: Send + Sync + 'static {
55    /// 发布事件,返回事件 ID。
56    async fn publish(&self, event: &PluginEvent) -> Result<EventId, String>;
57
58    /// 订阅事件,返回订阅 ID。
59    async fn subscribe(
60        &self,
61        event_type: &str,
62        handler: Arc<dyn EventHandler>,
63    ) -> Result<SubscriptionId, String>;
64
65    /// 取消订阅。
66    async fn unsubscribe(&self, sub_id: SubscriptionId) -> Result<(), String>;
67
68    /// 重放未投递事件(至少一次投递保障)。
69    async fn replay_pending(&self) -> Result<usize, String>;
70}
71
72/// 事件总线中的订阅表条目:订阅 ID + 处理器
73pub type SubscriptionEntry = (SubscriptionId, Arc<dyn EventHandler>);
74
75/// 事件总线中的订阅表:event_type → 订阅条目列表
76pub type SubscriptionMap = std::collections::HashMap<String, Vec<SubscriptionEntry>>;
77
78/// 内存事件总线实现(用于测试和轻量场景)。
79pub struct InMemoryEventBus {
80    /// 已发布事件记录(按序追加)
81    events: parking_lot::RwLock<Vec<PluginEvent>>,
82    /// 下一个事件 ID 计数器
83    next_id: parking_lot::Mutex<EventId>,
84    /// 订阅表:event_type → [(sub_id, handler)]
85    subscribers: parking_lot::RwLock<SubscriptionMap>,
86    /// 下一个订阅 ID 计数器
87    next_sub_id: parking_lot::Mutex<SubscriptionId>,
88}
89
90impl InMemoryEventBus {
91    /// 创建空的内存事件总线
92    pub fn new() -> Self {
93        Self {
94            events: parking_lot::RwLock::new(Vec::new()),
95            next_id: parking_lot::Mutex::new(1),
96            subscribers: parking_lot::RwLock::new(std::collections::HashMap::new()),
97            next_sub_id: parking_lot::Mutex::new(1),
98        }
99    }
100}
101
102impl Default for InMemoryEventBus {
103    fn default() -> Self {
104        Self::new()
105    }
106}
107
108#[async_trait]
109impl EventBus for InMemoryEventBus {
110    async fn publish(&self, event: &PluginEvent) -> Result<EventId, String> {
111        let id = {
112            let mut next = self.next_id.lock();
113            let id = *next;
114            *next += 1;
115            id
116        };
117        let mut event = event.clone();
118        event.id = id;
119        let event_type = event.event_type.clone();
120        self.events.write().push(event.clone());
121        let handlers: Vec<Arc<dyn EventHandler>> = {
122            let subs = self.subscribers.read();
123            subs.get(&event_type)
124                .map(|v| v.iter().map(|(_, h)| h.clone()).collect())
125                .unwrap_or_default()
126        };
127        for handler in handlers {
128            let _ = handler.handle(&event).await;
129        }
130        Ok(id)
131    }
132
133    async fn subscribe(
134        &self,
135        event_type: &str,
136        handler: Arc<dyn EventHandler>,
137    ) -> Result<SubscriptionId, String> {
138        let sub_id = {
139            let mut next = self.next_sub_id.lock();
140            let id = *next;
141            *next += 1;
142            id
143        };
144        let mut subs = self.subscribers.write();
145        subs.entry(event_type.to_string())
146            .or_default()
147            .push((sub_id, handler));
148        Ok(sub_id)
149    }
150
151    async fn unsubscribe(&self, sub_id: SubscriptionId) -> Result<(), String> {
152        let mut subs = self.subscribers.write();
153        for handlers in subs.values_mut() {
154            handlers.retain(|(id, _)| *id != sub_id);
155        }
156        Ok(())
157    }
158
159    async fn replay_pending(&self) -> Result<usize, String> {
160        Ok(0)
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    struct CountHandler {
169        count: parking_lot::Mutex<usize>,
170    }
171
172    #[async_trait]
173    impl EventHandler for CountHandler {
174        async fn handle(&self, _event: &PluginEvent) -> Result<(), String> {
175            *self.count.lock() += 1;
176            Ok(())
177        }
178    }
179
180    #[tokio::test]
181    async fn test_publish_and_subscribe() {
182        let bus = InMemoryEventBus::new();
183        let handler = Arc::new(CountHandler {
184            count: parking_lot::Mutex::new(0),
185        });
186        let _ = bus.subscribe("test.event", handler.clone()).await;
187        let event = PluginEvent {
188            id: 0,
189            tenant_id: 1,
190            event_type: "test.event".to_string(),
191            source_plugin: "test".to_string(),
192            payload: serde_json::json!({}),
193        };
194        let id = bus.publish(&event).await.expect("发布失败");
195        assert!(id > 0);
196        assert_eq!(*handler.count.lock(), 1);
197    }
198}