feat: simplify OpenRPC API and reorganize examples
- Simplified RunnerConfig to just name, command, and optional env - Removed RunnerType and ProcessManagerType enums - Removed db_path, redis_url, binary_path from config - Made runner name also serve as queue name (no separate queue param) - Added secret-based authentication to all runner management methods - Created comprehensive osiris_openrpc example - Archived old examples to _archive/ - Updated client API to match simplified supervisor interface
This commit is contained in:
		
							
								
								
									
										69
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								src/app.rs
									
									
									
									
									
								
							@@ -5,9 +5,12 @@
 | 
			
		||||
//! then pass it to SupervisorApp for runtime management.
 | 
			
		||||
 | 
			
		||||
use crate::Supervisor;
 | 
			
		||||
#[cfg(feature = "mycelium")]
 | 
			
		||||
use crate::mycelium::MyceliumIntegration;
 | 
			
		||||
use log::{info, error, debug};
 | 
			
		||||
#[cfg(feature = "mycelium")]
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
#[cfg(feature = "mycelium")]
 | 
			
		||||
use tokio::sync::Mutex;
 | 
			
		||||
 | 
			
		||||
/// Main supervisor application
 | 
			
		||||
@@ -54,37 +57,45 @@ impl SupervisorApp {
 | 
			
		||||
 | 
			
		||||
    /// Start the Mycelium integration
 | 
			
		||||
    async fn start_mycelium_integration(&self) -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
        // Skip Mycelium if URL is empty
 | 
			
		||||
        if self.mycelium_url.is_empty() {
 | 
			
		||||
            info!("Mycelium integration disabled (no URL provided)");
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        #[cfg(feature = "mycelium")]
 | 
			
		||||
        {
 | 
			
		||||
            // Skip Mycelium if URL is empty
 | 
			
		||||
            if self.mycelium_url.is_empty() {
 | 
			
		||||
                info!("Mycelium integration disabled (no URL provided)");
 | 
			
		||||
                return Ok(());
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            info!("Starting Mycelium integration...");
 | 
			
		||||
            
 | 
			
		||||
            let supervisor_for_mycelium = Arc::new(Mutex::new(self.supervisor.clone()));
 | 
			
		||||
            let mycelium_url = self.mycelium_url.clone();
 | 
			
		||||
            let topic = self.topic.clone();
 | 
			
		||||
            
 | 
			
		||||
            let mycelium_integration = MyceliumIntegration::new(
 | 
			
		||||
                supervisor_for_mycelium,
 | 
			
		||||
                mycelium_url,
 | 
			
		||||
                topic,
 | 
			
		||||
            );
 | 
			
		||||
            
 | 
			
		||||
            // Start the Mycelium integration in a background task
 | 
			
		||||
            let integration_handle = tokio::spawn(async move {
 | 
			
		||||
                if let Err(e) = mycelium_integration.start().await {
 | 
			
		||||
                    error!("Mycelium integration error: {}", e);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Give the integration a moment to start
 | 
			
		||||
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
 | 
			
		||||
            info!("Mycelium integration started successfully");
 | 
			
		||||
 | 
			
		||||
            // Store the handle for potential cleanup
 | 
			
		||||
            std::mem::forget(integration_handle); // For now, let it run in background
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        info!("Starting Mycelium integration...");
 | 
			
		||||
        
 | 
			
		||||
        let supervisor_for_mycelium = Arc::new(Mutex::new(self.supervisor.clone()));
 | 
			
		||||
        let mycelium_url = self.mycelium_url.clone();
 | 
			
		||||
        let topic = self.topic.clone();
 | 
			
		||||
        
 | 
			
		||||
        let mycelium_integration = MyceliumIntegration::new(
 | 
			
		||||
            supervisor_for_mycelium,
 | 
			
		||||
            mycelium_url,
 | 
			
		||||
            topic,
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        // Start the Mycelium integration in a background task
 | 
			
		||||
        let integration_handle = tokio::spawn(async move {
 | 
			
		||||
            if let Err(e) = mycelium_integration.start().await {
 | 
			
		||||
                error!("Mycelium integration error: {}", e);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Give the integration a moment to start
 | 
			
		||||
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
 | 
			
		||||
        info!("Mycelium integration started successfully");
 | 
			
		||||
 | 
			
		||||
        // Store the handle for potential cleanup
 | 
			
		||||
        std::mem::forget(integration_handle); // For now, let it run in background
 | 
			
		||||
        #[cfg(not(feature = "mycelium"))]
 | 
			
		||||
        {
 | 
			
		||||
            info!("Mycelium integration not enabled (compile with --features mycelium)");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ pub mod job;
 | 
			
		||||
pub mod supervisor;
 | 
			
		||||
pub mod app;
 | 
			
		||||
pub mod openrpc;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "mycelium")]
 | 
			
		||||
pub mod mycelium;
 | 
			
		||||
 | 
			
		||||
// Re-export main types for convenience
 | 
			
		||||
@@ -15,4 +17,6 @@ pub use runner::{Runner, RunnerConfig, RunnerResult, RunnerStatus};
 | 
			
		||||
pub use supervisor::{Supervisor, SupervisorBuilder, ProcessManagerType};
 | 
			
		||||
pub use runner_rust::{Job, JobBuilder, JobStatus, JobError, Client, ClientBuilder};
 | 
			
		||||
pub use app::SupervisorApp;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "mycelium")]
 | 
			
		||||
pub use mycelium::{MyceliumIntegration, MyceliumServer};
 | 
			
		||||
 
 | 
			
		||||
@@ -303,20 +303,88 @@ impl MyceliumIntegration {
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            "job.run" => {
 | 
			
		||||
                // Run job and wait for result (blocking)
 | 
			
		||||
                if let Some(param_obj) = params.as_array().and_then(|arr| arr.get(0)) {
 | 
			
		||||
                    let _secret = param_obj.get("secret")
 | 
			
		||||
                        .and_then(|v| v.as_str())
 | 
			
		||||
                        .ok_or("missing secret")?;
 | 
			
		||||
                    let _job = param_obj.get("job")
 | 
			
		||||
                    
 | 
			
		||||
                    let job_value = param_obj.get("job")
 | 
			
		||||
                        .ok_or("missing job")?;
 | 
			
		||||
                    
 | 
			
		||||
                    // TODO: Implement actual job execution
 | 
			
		||||
                    Ok(json!("job_queued"))
 | 
			
		||||
                    let timeout = param_obj.get("timeout")
 | 
			
		||||
                        .and_then(|v| v.as_u64())
 | 
			
		||||
                        .unwrap_or(60);
 | 
			
		||||
                    
 | 
			
		||||
                    // Deserialize the job
 | 
			
		||||
                    let job: runner_rust::job::Job = serde_json::from_value(job_value.clone())
 | 
			
		||||
                        .map_err(|e| format!("invalid job format: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    let job_id = job.id.clone();
 | 
			
		||||
                    let runner_name = job.runner.clone();
 | 
			
		||||
                    
 | 
			
		||||
                    // Verify signatures
 | 
			
		||||
                    job.verify_signatures()
 | 
			
		||||
                        .map_err(|e| format!("signature verification failed: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    info!("Job {} signature verification passed for signatories: {:?}", 
 | 
			
		||||
                          job_id, job.signatories());
 | 
			
		||||
                    
 | 
			
		||||
                    // Queue and wait for result
 | 
			
		||||
                    let mut supervisor_guard = self.supervisor.lock().await;
 | 
			
		||||
                    let result = supervisor_guard.queue_and_wait(&runner_name, job, timeout)
 | 
			
		||||
                        .await
 | 
			
		||||
                        .map_err(|e| format!("job execution failed: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    Ok(json!({
 | 
			
		||||
                        "job_id": job_id,
 | 
			
		||||
                        "status": "completed",
 | 
			
		||||
                        "result": result
 | 
			
		||||
                    }))
 | 
			
		||||
                } else {
 | 
			
		||||
                    Err("invalid job.run params".into())
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            "job.start" => {
 | 
			
		||||
                // Start job without waiting (non-blocking)
 | 
			
		||||
                if let Some(param_obj) = params.as_array().and_then(|arr| arr.get(0)) {
 | 
			
		||||
                    let _secret = param_obj.get("secret")
 | 
			
		||||
                        .and_then(|v| v.as_str())
 | 
			
		||||
                        .ok_or("missing secret")?;
 | 
			
		||||
                    
 | 
			
		||||
                    let job_value = param_obj.get("job")
 | 
			
		||||
                        .ok_or("missing job")?;
 | 
			
		||||
                    
 | 
			
		||||
                    // Deserialize the job
 | 
			
		||||
                    let job: runner_rust::job::Job = serde_json::from_value(job_value.clone())
 | 
			
		||||
                        .map_err(|e| format!("invalid job format: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    let job_id = job.id.clone();
 | 
			
		||||
                    let runner_name = job.runner.clone();
 | 
			
		||||
                    
 | 
			
		||||
                    // Verify signatures
 | 
			
		||||
                    job.verify_signatures()
 | 
			
		||||
                        .map_err(|e| format!("signature verification failed: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    info!("Job {} signature verification passed for signatories: {:?}", 
 | 
			
		||||
                          job_id, job.signatories());
 | 
			
		||||
                    
 | 
			
		||||
                    // Queue the job without waiting
 | 
			
		||||
                    let mut supervisor_guard = self.supervisor.lock().await;
 | 
			
		||||
                    supervisor_guard.queue_job_to_runner(&runner_name, job)
 | 
			
		||||
                        .await
 | 
			
		||||
                        .map_err(|e| format!("failed to queue job: {}", e))?;
 | 
			
		||||
                    
 | 
			
		||||
                    Ok(json!({
 | 
			
		||||
                        "job_id": job_id,
 | 
			
		||||
                        "status": "queued"
 | 
			
		||||
                    }))
 | 
			
		||||
                } else {
 | 
			
		||||
                    Err("invalid job.start params".into())
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            "job.status" => {
 | 
			
		||||
                if let Some(_job_id) = params.as_array().and_then(|arr| arr.get(0)).and_then(|v| v.as_str()) {
 | 
			
		||||
                    // TODO: Implement actual job status lookup
 | 
			
		||||
@@ -339,7 +407,7 @@ impl MyceliumIntegration {
 | 
			
		||||
                let methods = vec![
 | 
			
		||||
                    "list_runners", "register_runner", "start_runner", "stop_runner",
 | 
			
		||||
                    "get_runner_status", "get_all_runner_status", "start_all", "stop_all",
 | 
			
		||||
                    "job.run", "job.status", "job.result", "rpc.discover"
 | 
			
		||||
                    "job.run", "job.start", "job.status", "job.result", "rpc.discover"
 | 
			
		||||
                ];
 | 
			
		||||
                Ok(json!(methods))
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -330,7 +330,6 @@ pub trait SupervisorRpc {
 | 
			
		||||
    #[method(name = "queue_job_to_runner")]
 | 
			
		||||
    async fn queue_job_to_runner(&self, params: QueueJobParams) -> RpcResult<()>;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// Get a job by job ID
 | 
			
		||||
    #[method(name = "get_job")]
 | 
			
		||||
    async fn get_job(&self, job_id: String) -> RpcResult<Job>;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user