1use std::sync::Arc;
9use std::time::{Duration, Instant};
10
11use brokapi_alor_protocol::ws::models::WsIncoming;
12use brokapi_runtime::Emitter;
13use brokapi_sansio::{BrokerCore, EventSink};
14use kanal::AsyncReceiver;
15use tokio::sync::Mutex;
16use tokio_util::sync::CancellationToken;
17
18const FLUSH_EVERY: Duration = Duration::from_millis(20);
20
21pub async fn run_pump<C, F, Fut>(
27 core: Arc<Mutex<C>>,
28 emitter: Arc<Emitter>,
29 rx: AsyncReceiver<WsIncoming>,
30 cancel: CancellationToken,
31 before: F,
32) where
33 C: BrokerCore<Frame = WsIncoming>,
34 F: Fn(WsIncoming) -> Fut,
35 Fut: std::future::Future<Output = WsIncoming>,
36{
37 loop {
38 let backlog = emitter.has_backlog();
39 tokio::select! {
40 _ = cancel.cancelled() => break,
41 msg = rx.recv() => {
42 let Ok(msg) = msg else { break };
43 let msg = before(msg).await;
44 let now: Instant = brokapi_runtime::now();
45 let mut sink = EventSink::new();
46 core.lock().await.on_frame(msg, now, &mut sink);
47 emitter.emit(sink.drain());
48 }
49 _ = tokio::time::sleep(FLUSH_EVERY), if backlog => emitter.flush(),
50 }
51 }
52}
53
54pub async fn drain_backlog(emitter: &Emitter, deadline: Duration) {
56 let end = brokapi_runtime::now() + deadline;
57 while emitter.has_backlog() && brokapi_runtime::now() < end {
58 emitter.flush();
59 tokio::time::sleep(Duration::from_millis(5)).await;
60 }
61}