ek-event 0.1.2

Self-contained event engine in Rust, a faithful semantic replication of enkeep_trade's event engine. No dependency on enkeep_trade.
Documentation
//! P8 —— 批量事件模式:eTickStockBatch 等,data 为 list,handler 内逐条消费。

use ek_event::{Event, EventEngine};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;

fn wait_for(cond: impl Fn() -> bool) -> bool {
    for _ in 0..300 {
        if cond() {
            return true;
        }
        std::thread::sleep(Duration::from_millis(10));
    }
    cond()
}

#[derive(Clone, Debug)]
#[allow(dead_code)] // 仅 symbol 被断言读取,price 用于构造贴近真实 tick
struct TickMsg {
    symbol: String,
    price: f64,
}

// B1: 500 条批量 tick,list 载荷全收 + 顺序保持(复刻 _process_tick_event 的 list 分支)
#[test]
fn b1_batch_list_payload() {
    let engine = Arc::new(EventEngine::new());
    engine.start();

    let events_seen = Arc::new(AtomicUsize::new(0));
    let rows = Arc::new(Mutex::new(Vec::<(String, usize)>::new()));

    let r = rows.clone();
    let ev = events_seen.clone();
    engine.register(
        "eTickStockBatch",
        Arc::new(move |e| {
            ev.fetch_add(1, Ordering::SeqCst);
            let batch = e
                .data
                .downcast_ref::<Vec<TickMsg>>()
                .expect("Vec<TickMsg> payload");
            for (i, t) in batch.iter().enumerate() {
                r.lock().unwrap().push((t.symbol.clone(), i));
            }
        }),
    );

    const N: usize = 500;
    let batch: Vec<TickMsg> = (0..N)
        .map(|i| TickMsg {
            symbol: format!("S{i:04}"),
            price: i as f64,
        })
        .collect();
    engine
        .put(Event::with_data("eTickStockBatch", Arc::new(batch)))
        .unwrap();

    assert!(
        wait_for(|| events_seen.load(Ordering::SeqCst) == 1),
        "batch event delivered"
    );
    assert!(
        wait_for(|| rows.lock().unwrap().len() == N),
        "all 500 rows consumed"
    );
    let got = rows.lock().unwrap().clone();
    let idx_ok = got.iter().enumerate().all(|(k, (_, i))| k == *i);
    assert!(idx_ok, "batch iteration order must match the list order");
    assert_eq!(got[0].0, "S0000");
    assert_eq!(got[N - 1].0, "S0499");
    engine.stop();
}