Skip to main content

ek_event/
lib.rs

1//! ek-event —— 自包含事件引擎(Rust 复刻 enkeep_trade/event/engine.py)。
2//!
3//! 语义对齐原版:
4//! - 单分发线程串行处理(一个 type 的 handler 按注册顺序执行)
5//! - 无界队列
6//! - 独立定时线程,默认每 1 秒投递一个 [`EVENT_TIMER`] 事件
7//! - `stop()` 后队列中未处理的事件被丢弃(对齐原版)
8//!
9//! 对原版的修正:
10//! - handler 表全程 RwLock 保护
11//! - handler panic 被 catch_unwind 隔离,不再杀掉分发线程
12//! - 注册返回 [`HandlerId`],注销按 id(原版依赖函数对象相等,不可复刻)
13
14pub mod engine;
15pub mod event;
16pub mod handler;
17
18pub use engine::{EventEngine, PutError};
19pub use event::{Event, EventData};
20pub use handler::HandlerFn;
21pub use handler::HandlerId;
22pub use handler::HandlerRegistry;
23
24/// 定时事件类型串(与原版 `EVENT_TIMER = "eTimer"` 对齐)。
25pub const EVENT_TIMER: &str = "eTimer";
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use std::sync::atomic::{AtomicUsize, Ordering};
31    use std::sync::{Arc, Mutex};
32    use std::time::Duration;
33
34    /// 轮询条件直至成立,默认上限约 2 秒;结束前再判定一次(最后一次可能恰好在睡眠窗口内完成)。
35    fn wait_for(cond: impl Fn() -> bool) -> bool {
36        for _ in 0..200 {
37            if cond() {
38                return true;
39            }
40            std::thread::sleep(Duration::from_millis(10));
41        }
42        cond()
43    }
44
45    // T3: type handler 先执行,general handler 后执行(各按注册顺序)
46    #[test]
47    fn dispatch_order_type_then_general() {
48        let engine = EventEngine::new();
49        engine.start();
50        let seq: Arc<spin_free_seq::Seq> = Arc::default();
51        let s1 = seq.clone();
52        engine.register("eTick.", Arc::new(move |_| s1.record(0)));
53        let s2 = seq.clone();
54        engine.register_general(Arc::new(move |_| s2.record(1)));
55        // 聚合事件的 type 就是 "eTick." 本身(对齐 enkeep gateway: on_event(EVENT_TICK, tick));
56        // "eTick.600000" 是另一个精确 type,不会命中此处 handler。
57        engine.put(Event::new("eTick.")).unwrap();
58        for _ in 0..50 {
59            if seq.is(0, 1) {
60                break;
61            }
62            std::thread::sleep(Duration::from_millis(10));
63        }
64        // 期望值是 3(bit0 由 tick 置位,bit1 由 general handler 在 tick 或
65        // 周期 TIMER 事件上都可能置位),不是仅按单事件算出的 2。
66        assert_eq!(seq.0.load(Ordering::SeqCst) & 3, 3);
67        engine.stop();
68    }
69
70    // T4: 定时事件周期
71    #[test]
72    fn timer_event_fires() {
73        let engine = EventEngine::with_interval(Duration::from_millis(50));
74        engine.start();
75        let cnt = Arc::new(AtomicUsize::new(0));
76        let c2 = cnt.clone();
77        engine.register(
78            EVENT_TIMER,
79            Arc::new(move |_| {
80                c2.fetch_add(1, Ordering::SeqCst);
81            }),
82        );
83        std::thread::sleep(Duration::from_millis(400));
84        let n = cnt.load(Ordering::SeqCst);
85        assert!(n >= 3, "timer fired too few times: {n}");
86        engine.stop();
87    }
88
89    // T1: HandlerId 语义——每次注册产出全局唯一 id(防重复由上层负责)
90    #[test]
91    fn duplicate_registration_yields_unique_ids() {
92        let engine = EventEngine::new(); // 无需 start:注册与分发解耦
93        let bump = Arc::new(AtomicUsize::new(0));
94        let b1 = bump.clone();
95        let id1 = engine.register(
96            "eTick.",
97            Arc::new(move |_| {
98                b1.fetch_add(1, Ordering::SeqCst);
99            }),
100        );
101        let b2 = bump.clone();
102        let id2 = engine.register(
103            "eTick.",
104            Arc::new(move |_| {
105                b2.fetch_add(1, Ordering::SeqCst);
106            }),
107        );
108        assert_ne!(id1, id2, "each registration must get a unique HandlerId");
109        assert!(engine.unregister(id1));
110        assert!(engine.unregister(id2));
111        assert!(!engine.unregister(id1), "double unregister must be false");
112    }
113
114    // T5: handler panic 被 catch_unwind 隔离——后续 handler 与后续事件继续处理
115    #[test]
116    fn handler_panic_does_not_kill_dispatcher() {
117        let engine = EventEngine::new();
118        engine.start();
119        let cnt = Arc::new(AtomicUsize::new(0));
120        // 排在第一个的 handler 必 panic
121        let _ = engine.register(
122            "eTick.",
123            Arc::new(move |_| {
124                panic!("boom");
125            }),
126        );
127        let c2 = cnt.clone();
128        engine.register(
129            "eTick.",
130            Arc::new(move |_| {
131                c2.fetch_add(1, Ordering::SeqCst);
132            }),
133        );
134        engine.put(Event::new("eTick.")).unwrap();
135        assert!(
136            wait_for(|| cnt.load(Ordering::SeqCst) >= 1),
137            "handler after a panicking one must still run"
138        );
139        engine.put(Event::new("eTick.")).unwrap();
140        assert!(
141            wait_for(|| cnt.load(Ordering::SeqCst) >= 2),
142            "events dispatched after a handler panic must still be processed"
143        );
144        engine.stop();
145    }
146
147    // T6: stop 后 put 报 Stopped;stop 重复调用幂等
148    #[test]
149    fn put_after_stop_fails_and_stop_is_idempotent() {
150        let engine = EventEngine::new();
151        engine.start();
152        engine.stop();
153        assert!(!engine.is_active());
154        assert_eq!(engine.put(Event::new("eTick.")), Err(PutError::Stopped));
155        engine.stop(); // 二次 stop:幂等,不 panic
156        engine.stop(); // 三次
157        assert_eq!(engine.pending_events(), 0, "stop must reset pending count");
158    }
159
160    // T8: 同一 type 的事件按 put 顺序送达(单分发线程串行)
161    #[test]
162    fn same_type_events_delivered_in_put_order() {
163        let engine = EventEngine::new();
164        engine.start();
165        let seen: Arc<Mutex<Vec<usize>>> = Arc::default();
166        let s = seen.clone();
167        let _ = engine.register(
168            "eTick.",
169            Arc::new(move |e| {
170                let v = *e.data.downcast_ref::<usize>().expect("usize payload");
171                s.lock().unwrap().push(v);
172            }),
173        );
174        const N: usize = 200;
175        for i in 0..N {
176            engine.put(Event::with_data("eTick.", Arc::new(i))).unwrap();
177        }
178        assert!(
179            wait_for(|| seen.lock().unwrap().len() >= N),
180            "all events must be delivered"
181        );
182        let expected: Vec<usize> = (0..N).collect();
183        assert_eq!(
184            *seen.lock().unwrap(),
185            expected,
186            "delivery must preserve put order"
187        );
188        engine.stop();
189    }
190
191    // T7(轻量版):多线程经 Arc 共享引擎并发 put / start 可在任意线程调用
192    // —— 能编译即证明 EventEngine: Sync + Send(裸 Receiver / &mut stop 的旧缺陷在此断言)
193    #[test]
194    fn event_engine_is_sync_and_concurrent_put_works() {
195        fn assert_send_sync<T: Send + Sync>() {}
196        assert_send_sync::<EventEngine>();
197
198        let engine = Arc::new(EventEngine::new());
199        engine.start(); // &self,可在共享后启动
200        let cnt = Arc::new(AtomicUsize::new(0));
201        let c = cnt.clone();
202        engine.register(
203            "eTick.",
204            Arc::new(move |_| {
205                c.fetch_add(1, Ordering::SeqCst);
206            }),
207        );
208        let mut handles = Vec::new();
209        for _ in 0..4 {
210            let e = engine.clone();
211            handles.push(std::thread::spawn(move || {
212                for _ in 0..50 {
213                    e.put(Event::new("eTick.")).unwrap();
214                }
215            }));
216        }
217        for h in handles {
218            h.join().unwrap();
219        }
220        const N: usize = 200;
221        assert!(
222            wait_for(|| cnt.load(Ordering::SeqCst) >= N),
223            "all cross-thread events must be delivered"
224        );
225        engine.stop();
226    }
227
228    // 内部测试用辅助:记录到达顺序(仅测试内使用)
229    mod spin_free_seq {
230        use std::sync::atomic::{AtomicI64, Ordering};
231        pub struct Seq(pub AtomicI64);
232        impl Seq {
233            pub fn record(&self, i: i64) {
234                let _ = self.0.fetch_or(1 << i, Ordering::SeqCst);
235            }
236            pub fn is(&self, a: i64, b: i64) -> bool {
237                self.0.load(Ordering::SeqCst) == (1 << a) + (1 << b)
238            }
239        }
240        impl Default for Seq {
241            fn default() -> Self {
242                Self(AtomicI64::new(0))
243            }
244        }
245    }
246}