Mountain/RPC/CocoonService/TreeView/
EnqueueTreeViewEmit.rs1#![allow(non_snake_case)]
2
3use std::{
10 sync::{
11 Arc,
12 Mutex,
13 OnceLock,
14 atomic::{AtomicBool, Ordering},
15 },
16 time::Duration,
17};
18
19use serde_json::{Value, json};
20use tauri::{AppHandle, Emitter};
21use CommonLibrary::IPC::SkyEvent::SkyEvent;
22
23use crate::dev_log;
24
25struct Batch {
26 Pending:Mutex<Vec<Value>>,
27 FlushScheduled:AtomicBool,
28}
29
30static BATCH:OnceLock<Arc<Batch>> = OnceLock::new();
31
32pub fn Fn(Handle:&AppHandle, Payload:Value) {
33 let Batch =
34 BATCH.get_or_init(|| Arc::new(Batch { Pending:Mutex::new(Vec::new()), FlushScheduled:AtomicBool::new(false) }));
35
36 {
37 let mut Pending = Batch.Pending.lock().unwrap();
38 Pending.push(Payload);
39 }
40
41 if !Batch.FlushScheduled.swap(true, Ordering::AcqRel) {
42 let Cloned = Batch.clone();
43 let HandleCloned = Handle.clone();
44 let Channel = SkyEvent::TreeViewCreate.AsStr().to_string();
45 tokio::spawn(async move {
46 tokio::time::sleep(Duration::from_millis(16)).await;
47 let Drained:Vec<Value> = {
48 let mut Pending = Cloned.Pending.lock().unwrap();
49 std::mem::take(&mut *Pending)
50 };
51 Cloned.FlushScheduled.store(false, Ordering::Release);
52 if Drained.is_empty() {
53 return;
54 }
55 let Count = Drained.len();
56 match HandleCloned.emit(&Channel, json!({ "views": Drained })) {
57 Ok(()) => dev_log!("sky-emit", "[SkyEmit] ok channel={} batch={}", Channel, Count),
58 Err(Error) => {
59 dev_log!("sky-emit", "[SkyEmit] fail channel={} batch={} error={}", Channel, Count, Error)
60 },
61 }
62 });
63 }
64}