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
28 FlushScheduled:AtomicBool,
29}
30
31static BATCH:OnceLock<Arc<Batch>> = OnceLock::new();
32
33pub fn Fn(Handle:&AppHandle, Payload:Value) {
34 let Batch =
35 BATCH.get_or_init(|| Arc::new(Batch { Pending:Mutex::new(Vec::new()), FlushScheduled:AtomicBool::new(false) }));
36
37 {
38 let mut Pending = Batch.Pending.lock().unwrap();
39
40 Pending.push(Payload);
41 }
42
43 if !Batch.FlushScheduled.swap(true, Ordering::AcqRel) {
44 let Cloned = Batch.clone();
45
46 let HandleCloned = Handle.clone();
47
48 let Channel = SkyEvent::TreeViewCreate.AsStr().to_string();
49
50 tokio::spawn(async move {
51 tokio::time::sleep(Duration::from_millis(16)).await;
52 let Drained:Vec<Value> = {
53 let mut Pending = Cloned.Pending.lock().unwrap();
54 std::mem::take(&mut *Pending)
55 };
56 Cloned.FlushScheduled.store(false, Ordering::Release);
57 if Drained.is_empty() {
58 return;
59 }
60 let Count = Drained.len();
61 match HandleCloned.emit(&Channel, json!({ "views": Drained })) {
62 Ok(()) => dev_log!("sky-emit", "[SkyEmit] ok channel={} batch={}", Channel, Count),
63 Err(Error) => {
64 dev_log!("sky-emit", "[SkyEmit] fail channel={} batch={} error={}", Channel, Count, Error)
65 },
66 }
67 });
68 }
69}