Plugin init/dispose

This commit is contained in:
Gregory Schier
2025-07-26 14:28:59 -07:00
parent 0d98b95b61
commit 38529cc89e
12 changed files with 101 additions and 85 deletions

View File

@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use tauri::{Runtime, WebviewWindow};
use ts_rs::TS;
@@ -64,10 +65,9 @@ impl PluginWindowContext {
#[ts(export, export_to = "gen_events.ts")]
pub enum InternalEventPayload {
BootRequest(BootRequest),
BootResponse(BootResponse),
BootResponse,
ReloadRequest(EmptyPayload),
ReloadResponse(BootResponse),
ReloadResponse(ReloadResponse),
TerminateRequest,
TerminateResponse,
@@ -161,6 +161,17 @@ pub enum InternalEventPayload {
ErrorResponse(ErrorResponse),
}
impl InternalEventPayload {
pub fn type_name(&self) -> String {
if let Ok(Value::Object(map)) = serde_json::to_value(self) {
map.get("type").map(|s| s.as_str().unwrap_or("unknown").to_string())
} else {
None
}
.unwrap_or("invalid_event".to_string())
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default)]
#[ts(export, type = "{}", export_to = "gen_events.ts")]
@@ -184,9 +195,8 @@ pub struct BootRequest {
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct BootResponse {
pub name: String,
pub version: String,
pub struct ReloadResponse {
pub silent: bool,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]

View File

@@ -19,7 +19,7 @@ use crate::nodejs::start_nodejs_plugin_runtime;
use crate::plugin_handle::PluginHandle;
use crate::server_ws::PluginRuntimeServerWebsocket;
use crate::template_callback::PluginTemplateCallback;
use log::{error, info, warn};
use log::{debug, error, info, warn};
use serde_json::json;
use std::collections::HashMap;
use std::env;
@@ -31,6 +31,7 @@ use tauri::{AppHandle, Manager, Runtime, WebviewWindow, is_dev};
use tokio::fs::read_dir;
use tokio::net::TcpListener;
use tokio::sync::{Mutex, mpsc};
use tokio::sync::mpsc::error::TrySendError;
use tokio::time::{Instant, timeout};
use yaak_models::models::Environment;
use yaak_models::query_manager::QueryManagerExt;
@@ -91,7 +92,14 @@ impl PluginManager {
while let Some(event) = events_rx.recv().await {
for (tx_id, tx) in subscribers.lock().await.iter_mut() {
if let Err(e) = tx.try_send(event.clone()) {
warn!("Failed to send event to subscriber {tx_id} {e:?}");
match e {
TrySendError::Full(e) => {
error!("Failed to send event to full subscriber {tx_id} {e:?}");
}
TrySendError::Closed(_) => {
// Subscriber already unsubscribed
}
}
}
}
}
@@ -240,17 +248,14 @@ impl PluginManager {
)
.await??;
let mut plugins = self.plugins.lock().await;
if !matches!(event.payload, InternalEventPayload::BootResponse) {
return Err(UnknownEventErr);
}
// Remove the existing plugin (if exists) before adding this one
let mut plugins = self.plugins.lock().await;
plugins.retain(|p| p.dir != dir);
plugins.push(plugin_handle.clone());
let _ = match event.payload {
InternalEventPayload::BootResponse(resp) => resp,
_ => return Err(UnknownEventErr),
};
Ok(())
}
@@ -363,7 +368,7 @@ impl PluginManager {
payload: &InternalEventPayload,
plugins: Vec<PluginHandle>,
) -> Result<Vec<InternalEvent>> {
let label = format!("wait[{}]", plugins.len());
let label = format!("wait[{}.{}]", plugins.len(), payload.type_name());
let (rx_id, mut rx) = self.subscribe(label.as_str()).await;
// 1. Build the events with IDs and everything
@@ -411,7 +416,7 @@ impl PluginManager {
let events = sub_events_fut.await.expect("Thread didn't succeed");
// 5. Unsubscribe
self.unsubscribe(rx_id.as_str()).await;
self.unsubscribe(&rx_id).await;
Ok(events)
}

View File

@@ -2,7 +2,6 @@ use crate::error::Result;
use crate::events::{InternalEvent, InternalEventPayload, PluginWindowContext};
use crate::plugin_meta::{PluginMetadata, get_plugin_meta};
use crate::util::gen_id;
use log::info;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::{Mutex, mpsc};
@@ -58,13 +57,6 @@ impl PluginHandle {
}
}
pub async fn terminate(&self, window_context: &PluginWindowContext) -> Result<()> {
info!("Terminating plugin {}", self.dir);
let event =
self.build_event_to_send(window_context, &InternalEventPayload::TerminateRequest, None);
self.send(&event).await
}
pub async fn send(&self, event: &InternalEvent) -> Result<()> {
self.to_plugin_tx.lock().await.send(event.to_owned()).await?;
Ok(())