DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/Vine/Server/Notification/
RegisterCommand.rs1use std::sync::OnceLock;
20
21use serde_json::{Value, json};
22use tauri::{AppHandle, Emitter};
23use tokio::sync::mpsc::{UnboundedSender, unbounded_channel};
24
25use crate::{
26 Environment::CommandProvider::CommandHandler,
27 Vine::Server::MountainVinegRPCService::MountainVinegRPCService,
28 dev_log,
29};
30
31struct CommandBatchChannel {
32 Sender:UnboundedSender<(AppHandle, Value)>,
33}
34
35static CMD_CHANNEL:OnceLock<CommandBatchChannel> = OnceLock::new();
36
37fn GetOrInitChannel(Handle:&AppHandle) -> &'static CommandBatchChannel {
38 CMD_CHANNEL.get_or_init(|| {
39 let (Tx, mut Rx) = unbounded_channel::<(AppHandle, Value)>();
40
41 tokio::spawn(async move {
42 let mut Buf:Vec<(AppHandle, Value)> = Vec::with_capacity(128);
43
44 loop {
45 match Rx.recv().await {
47 None => break,
48 Some(First) => Buf.push(First),
49 }
50
51 Rx.recv_many(&mut Buf, 4096).await;
53
54 tokio::time::sleep(std::time::Duration::from_millis(16)).await;
56
57 Rx.recv_many(&mut Buf, 4096).await;
59
60 if Buf.is_empty() {
61 continue;
62 }
63
64 let Handle = Buf[0].0.clone();
66
67 let Commands:Vec<Value> = Buf.drain(..).map(|(_, V)| V).collect();
68
69 let Count = Commands.len();
70
71 match Handle.emit("sky://command/register", json!({ "commands": Commands })) {
72 Ok(()) => {
73 dev_log!("sky-emit", "[SkyEmit] ok channel=sky://command/register batch={}", Count);
74
75 dev_log!("commands", "[RegisterCommand] batch={}", Count);
83 },
84 Err(E) => {
85 dev_log!(
86 "sky-emit",
87 "[SkyEmit] fail channel=sky://command/register batch={} error={}",
88 Count,
89 E
90 );
91 },
92 }
93 }
94 });
95
96 CommandBatchChannel { Sender:Tx }
97 })
98}
99
100pub async fn RegisterCommand(Service:&MountainVinegRPCService, Parameter:&Value) {
101 let CommandId = Parameter.get("commandId").and_then(Value::as_str).unwrap_or("");
102
103 dev_log!(
104 "command-register",
105 "[MountainVinegRPCService] Cocoon registered command: {}",
106 CommandId
107 );
108
109 if CommandId.is_empty() {
110 return;
111 }
112
113 let Kind = Parameter.get("kind").and_then(Value::as_str).unwrap_or("command").to_string();
114
115 if let Ok(mut Registry) = Service
116 .RunTime()
117 .Environment
118 .ApplicationState
119 .Extension
120 .Registry
121 .CommandRegistry
122 .lock()
123 {
124 Registry.insert(
125 CommandId.to_string(),
126 CommandHandler::Proxied {
127 SideCarIdentifier:"cocoon-main".to_string(),
128 CommandIdentifier:CommandId.to_string(),
129 },
130 );
131 }
132
133 let Ch = GetOrInitChannel(Service.ApplicationHandle());
134
135 let _ = Ch.Sender.send((
136 Service.ApplicationHandle().clone(),
137 json!({ "id": CommandId, "commandId": CommandId, "kind": Kind }),
138 ));
139}