Skip to main content

Mountain/RPC/CocoonService/TreeView/
EnqueueTreeViewEmit.rs

1
2//! Coalesce 30+ Mountain → Sky `tree-view/create` emits at boot into a
3//! single batched payload per frame. Uses the channel-drain pattern: a
4//! long-lived flusher wakes on first item, drains immediately, sleeps one
5//! frame (16 ms), drains stragglers, then emits one `{ views: [...] }` batch.
6//! Zero spawns per call; sub-millisecond wake latency.
7
8use std::sync::OnceLock;
9
10use serde_json::{Value, json};
11use tauri::{AppHandle, Emitter};
12use tokio::sync::mpsc::{UnboundedSender, unbounded_channel};
13use CommonLibrary::IPC::SkyEvent::SkyEvent;
14
15use crate::dev_log;
16
17struct TreeViewChannel {
18	Sender:UnboundedSender<(AppHandle, Value)>,
19}
20
21static TV_CH:OnceLock<TreeViewChannel> = OnceLock::new();
22
23fn GetOrInitChannel(Handle:&AppHandle) -> &'static TreeViewChannel {
24	TV_CH.get_or_init(|| {
25		let (Tx, mut Rx) = unbounded_channel::<(AppHandle, Value)>();
26
27		let Channel = SkyEvent::TreeViewCreate.AsStr().to_string();
28
29		tokio::spawn(async move {
30			let mut Buf:Vec<(AppHandle, Value)> = Vec::with_capacity(64);
31
32			loop {
33				match Rx.recv().await {
34					None => break,
35					Some(Item) => Buf.push(Item),
36				}
37
38				Rx.recv_many(&mut Buf, 4096).await;
39
40				tokio::time::sleep(std::time::Duration::from_millis(16)).await;
41
42				Rx.recv_many(&mut Buf, 4096).await;
43
44				if Buf.is_empty() {
45					continue;
46				}
47
48				let Handle = Buf[0].0.clone();
49
50				let Views:Vec<Value> = Buf.drain(..).map(|(_, V)| V).collect();
51
52				let Count = Views.len();
53
54				match Handle.emit(&Channel, json!({ "views": Views })) {
55					Ok(()) => dev_log!("sky-emit", "[SkyEmit] ok channel={} batch={}", Channel, Count),
56					Err(E) => {
57						dev_log!("sky-emit", "[SkyEmit] fail channel={} batch={} error={}", Channel, Count, E)
58					},
59				}
60			}
61		});
62
63		TreeViewChannel { Sender:Tx }
64	})
65}
66
67pub fn Fn(Handle:&AppHandle, Payload:Value) {
68	let Ch = GetOrInitChannel(Handle);
69
70	let _ = Ch.Sender.send((Handle.clone(), Payload));
71}