This commit is contained in:
Maxime Van Hees
2025-08-14 14:14:34 +02:00
parent 04a1af2423
commit 0ebda7c1aa
59 changed files with 6950 additions and 354 deletions

View File

@@ -1,6 +1,6 @@
use anyhow::Result;
use hero_job::{Job, JobBuilder, JobStatus, ScriptType};
use hero_supervisor::{Supervisor, SupervisorBuilder};
use hero_supervisor::{Supervisor, SupervisorBuilder, SupervisorError};
use jsonrpsee::core::async_trait;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::server::{ServerBuilder, ServerHandle};
@@ -12,17 +12,24 @@ use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::error;
fn map_sup_error_to_rpc(e: &SupervisorError) -> ErrorCode {
match e {
SupervisorError::InvalidInput(_) | SupervisorError::JobError(_) => ErrorCode::InvalidParams,
SupervisorError::Timeout(_) => ErrorCode::ServerError(-32002),
_ => ErrorCode::InternalError,
}
}
mod auth;
pub mod types;
pub use auth::*;
pub use types::*;
/// Transport type for the OpenRPC server
/** Transport type for the OpenRPC server */
#[derive(Debug, Clone)]
pub enum Transport {
WebSocket(SocketAddr),
Unix(PathBuf),
}
/// OpenRPC server configuration
@@ -82,7 +89,7 @@ pub trait OpenRpcApi {
async fn get_job_logs(&self, job_id: String) -> Result<JobLogsResult, ErrorCode>;
#[method(name = "list_jobs")]
async fn list_jobs(&self) -> Result<Vec<Job>, ErrorCode>;
async fn list_jobs(&self) -> Result<Vec<String>, ErrorCode>;
#[method(name = "stop_job")]
async fn stop_job(&self, job_id: String) -> Result<(), ErrorCode>;
@@ -114,8 +121,8 @@ impl OpenRpcServer {
})
}
/// Start the OpenRPC server
pub async fn start(self, config: OpenRpcServerConfig) -> Result<ServerHandle> {
/// Start the OpenRPC server on the given SocketAddr (HTTP/WS only)
pub async fn start_on(self, addr: SocketAddr) -> Result<ServerHandle> {
let mut module = RpcModule::new(());
// Register all the RPC methods
@@ -244,18 +251,17 @@ impl OpenRpcServer {
}
})?;
let server = ServerBuilder::default()
.build(addr)
.await?;
let handle = server.start(module);
Ok(handle)
}
/// Start the OpenRPC server (config wrapper)
pub async fn start(self, config: OpenRpcServerConfig) -> Result<ServerHandle> {
match config.transport {
Transport::WebSocket(addr) => {
let server = ServerBuilder::default()
.build(addr)
.await?;
let handle = server.start(module);
Ok(handle)
}
Transport::Unix(_path) => {
// Unix socket transport not yet implemented in jsonrpsee 0.21
return Err(anyhow::anyhow!("Unix socket transport not yet supported").into());
}
Transport::WebSocket(addr) => self.start_on(addr).await,
}
}
}
@@ -295,12 +301,8 @@ impl OpenRpcApiServer for OpenRpcServer {
}
async fn play(&self, script: String) -> Result<PlayResult, ErrorCode> {
let _supervisor = self.supervisor.read().await;
// For now, return a simple result since we need to implement execute_script method
Ok(PlayResult {
output: format!("Script executed: {}", script)
})
let output = self.run_job(script, ScriptType::SAL, None).await?;
Ok(PlayResult { output })
}
async fn create_job(&self, job_params: JobParams) -> Result<String, ErrorCode> {
@@ -360,10 +362,37 @@ impl OpenRpcApiServer for OpenRpcServer {
&self,
script: String,
script_type: ScriptType,
_prerequisites: Option<Vec<String>>,
prerequisites: Option<Vec<String>>,
) -> Result<String, ErrorCode> {
// For now, return a simple result
Ok(format!("Job executed with script: {} (type: {:?})", script, script_type))
let supervisor = self.supervisor.read().await;
// Build job with defaults and optional prerequisites
let mut builder = JobBuilder::new()
.caller_id("rpc-caller")
.context_id("rpc-context")
.script(&script)
.script_type(script_type)
.timeout(std::time::Duration::from_secs(30));
if let Some(prs) = prerequisites {
builder = builder.prerequisites(prs);
}
let job = match builder.build() {
Ok(j) => j,
Err(e) => {
error!("Failed to build job in run_job: {}", e);
return Err(ErrorCode::InvalidParams);
}
};
match supervisor.run_job_and_await_result(&job).await {
Ok(output) => Ok(output),
Err(e) => {
error!("run_job failed: {}", e);
Err(map_sup_error_to_rpc(&e))
}
}
}
async fn get_job_status(&self, job_id: String) -> Result<JobStatus, ErrorCode> {
@@ -373,7 +402,7 @@ impl OpenRpcApiServer for OpenRpcServer {
Ok(status) => Ok(status),
Err(e) => {
error!("Failed to get job status for {}: {}", job_id, e);
Err(ErrorCode::InvalidParams)
Err(map_sup_error_to_rpc(&e))
}
}
}
@@ -385,50 +414,29 @@ impl OpenRpcApiServer for OpenRpcServer {
Ok(output) => Ok(output.unwrap_or_else(|| "No output available".to_string())),
Err(e) => {
error!("Failed to get job output for {}: {}", job_id, e);
Err(ErrorCode::InvalidParams)
Err(map_sup_error_to_rpc(&e))
}
}
}
async fn get_job_logs(&self, job_id: String) -> Result<JobLogsResult, ErrorCode> {
// For now, return mock logs
Ok(JobLogsResult {
logs: format!("Logs for job {}", job_id),
})
let supervisor = self.supervisor.read().await;
match supervisor.get_job_logs(&job_id).await {
Ok(logs_opt) => Ok(JobLogsResult { logs: logs_opt }),
Err(e) => {
error!("Failed to get job logs for {}: {}", job_id, e);
Err(map_sup_error_to_rpc(&e))
}
}
}
async fn list_jobs(&self) -> Result<Vec<Job>, ErrorCode> {
async fn list_jobs(&self) -> Result<Vec<String>, ErrorCode> {
let supervisor = self.supervisor.read().await;
match supervisor.list_jobs().await {
Ok(job_ids) => {
// For now, create minimal Job objects with just the IDs
// In a real implementation, we'd need a supervisor.get_job() method
let jobs: Vec<Job> = job_ids.into_iter().map(|job_id| {
// Create a minimal job object - this is a temporary solution
// until supervisor.get_job() is implemented
Job {
id: job_id,
caller_id: "unknown".to_string(),
context_id: "unknown".to_string(),
script: "unknown".to_string(),
script_type: ScriptType::OSIS,
timeout: std::time::Duration::from_secs(30),
retries: 0,
concurrent: false,
log_path: None,
env_vars: std::collections::HashMap::new(),
prerequisites: Vec::new(),
dependents: Vec::new(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
}
}).collect();
Ok(jobs)
},
Ok(job_ids) => Ok(job_ids),
Err(e) => {
error!("Failed to list jobs: {}", e);
Err(ErrorCode::InternalError)
Err(map_sup_error_to_rpc(&e))
}
}
}
@@ -440,7 +448,7 @@ impl OpenRpcApiServer for OpenRpcServer {
Ok(_) => Ok(()),
Err(e) => {
error!("Failed to stop job {}: {}", job_id, e);
Err(ErrorCode::InvalidParams)
Err(map_sup_error_to_rpc(&e))
}
}
}
@@ -452,7 +460,7 @@ impl OpenRpcApiServer for OpenRpcServer {
Ok(_) => Ok(()),
Err(e) => {
error!("Failed to delete job {}: {}", job_id, e);
Err(ErrorCode::InvalidParams)
Err(map_sup_error_to_rpc(&e))
}
}
}
@@ -464,7 +472,7 @@ impl OpenRpcApiServer for OpenRpcServer {
Ok(_) => Ok(()),
Err(e) => {
error!("Failed to clear all jobs: {}", e);
Err(ErrorCode::InternalError)
Err(map_sup_error_to_rpc(&e))
}
}
}

View File

@@ -24,8 +24,8 @@ pub struct StartJobResult {
pub success: bool,
}
/// Result of getting job logs
/** Result of getting job logs */
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct JobLogsResult {
pub logs: String,
pub logs: Option<String>,
}