use gloo::console; use std::rc::Rc; use std::cell::RefCell; use crate::wasm_client::{WasmSupervisorClient, WasmClientResult as ClientResult, RunnerConfig, ProcessManagerType, ProcessStatus, LogInfo, Job, RunnerType}; use wasm_bindgen_futures::spawn_local; use yew::prelude::*; use crate::types::{RunnerInfo, AppState}; /// Service for managing supervisor client operations #[derive(Clone)] pub struct SupervisorService { client: Rc>, } impl PartialEq for SupervisorService { fn eq(&self, other: &Self) -> bool { // Compare by server URL since that's the main identifier self.client.borrow().server_url() == other.client.borrow().server_url() } } impl SupervisorService { pub fn new(server_url: &str) -> ClientResult { let client = WasmSupervisorClient::new(server_url); Ok(Self { client: Rc::new(RefCell::new(client)), }) } /// Get all runners with their status and basic info pub async fn get_all_runners(&self) -> ClientResult> { let runner_ids = self.client.borrow_mut().list_runners().await?; let mut runners = Vec::new(); for id in runner_ids { let status = self.client.borrow_mut().get_runner_status(&id).await.unwrap_or(ProcessStatus::Unknown); let logs = self.client.borrow_mut().get_runner_logs(&id, Some(50), false).await.unwrap_or_default(); // Create a basic runner config since we don't have a get_runner_config method let config = RunnerConfig { actor_id: id.clone(), runner_type: RunnerType::SALRunner, // Default binary_path: std::path::PathBuf::from("unknown"), script_type: "unknown".to_string(), args: vec![], env_vars: std::collections::HashMap::new(), working_dir: None, restart_policy: "always".to_string(), health_check_command: None, dependencies: vec![], }; runners.push(RunnerInfo { id, config, status, logs, }); } Ok(runners) } /// Add a new runner pub async fn add_runner(&self, config: RunnerConfig, process_manager_type: ProcessManagerType) -> ClientResult<()> { self.client.borrow_mut().add_runner(config, process_manager_type).await } /// Remove a runner pub async fn remove_runner(&self, actor_id: &str) -> ClientResult<()> { self.client.borrow_mut().remove_runner(actor_id).await } /// Start a runner pub async fn start_runner(&self, actor_id: &str) -> ClientResult<()> { self.client.borrow_mut().start_runner(actor_id).await } /// Stop a runner pub async fn stop_runner(&self, actor_id: &str, force: bool) -> ClientResult<()> { self.client.borrow_mut().stop_runner(actor_id, force).await } /// Get runner status pub async fn get_runner_status(&self, actor_id: &str) -> ClientResult { self.client.borrow_mut().get_runner_status(actor_id).await } /// Get runner logs pub async fn get_runner_logs(&self, actor_id: &str, lines: Option, follow: bool) -> ClientResult> { self.client.borrow_mut().get_runner_logs(actor_id, lines, follow).await } /// Start all runners pub async fn start_all(&self) -> ClientResult> { self.client.borrow_mut().start_all().await } /// Stop all runners pub async fn stop_all(&self, force: bool) -> ClientResult> { self.client.borrow_mut().stop_all(force).await } /// Queue a job to a runner pub async fn queue_job(&self, runner: &str, job: Job) -> ClientResult<()> { self.client.borrow_mut().queue_job_to_runner(runner, job).await } /// Queue a job and wait for result pub async fn queue_and_wait(&self, runner: &str, job: Job, timeout_secs: u64) -> ClientResult> { self.client.borrow_mut().queue_and_wait(runner, job, timeout_secs).await } } /// Hook for managing supervisor service state #[hook] pub fn use_supervisor_service(server_url: &str) -> (Option, Option) { let server_url = server_url.to_string(); let service_state = use_state(|| None); let error_state = use_state(|| None); { let service_state = service_state.clone(); let error_state = error_state.clone(); let server_url = server_url.clone(); use_effect_with(server_url.clone(), move |_| { spawn_local(async move { match SupervisorService::new(&server_url) { Ok(service) => { service_state.set(Some(service)); error_state.set(None); } Err(e) => { console::error!("Failed to create supervisor service:", e.to_string()); error_state.set(Some(e.to_string())); } } }); }); } ((*service_state).clone(), (*error_state).clone()) }