Files
horus/lib/clients/coordinator/src/models.rs
Timur Gordon f66edba1d3 Add coordinator client library, installation scripts, and new test runners
- Add coordinator client library to workspace
- Add installation documentation and heroscript
- Add new test runners for Osiris and Sal
- Update hero runner test to handle invalid heroscript errors
- Update README with installation instructions
2025-11-17 10:56:13 +01:00

249 lines
5.9 KiB
Rust

//! Data models for the Coordinator client
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::IpAddr;
// Re-export Job types from hero_job
pub use hero_job::{Job, JobStatus};
/// Timestamp type (Unix timestamp in seconds)
pub type Timestamp = u64;
// ==================== Actor ====================
/// Actor representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Actor {
pub id: u32,
pub pubkey: String,
pub address: Vec<IpAddr>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
}
/// Parameters for creating an actor
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActorCreate {
pub id: u32,
pub pubkey: String,
pub address: Vec<IpAddr>,
}
// ==================== Context ====================
/// Context representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Context {
/// Redis DB to use
pub id: u32,
/// Actor ids which have admin rights on this context
pub admins: Vec<u32>,
/// Actor ids which can read the context info
pub readers: Vec<u32>,
/// Actor ids which can execute jobs in this context
pub executors: Vec<u32>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
}
/// Parameters for creating a context
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextCreate {
pub id: u32,
pub admins: Vec<u32>,
pub readers: Vec<u32>,
pub executors: Vec<u32>,
}
// ==================== Runner ====================
/// Runner representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Runner {
pub id: u32,
/// Mycelium public key
pub pubkey: String,
/// Mycelium address
pub address: IpAddr,
/// Message topic (e.g., "supervisor.rpc")
pub topic: String,
/// Script type this runner supports
pub script_type: ScriptType,
/// If true, the runner also listens on a local redis queue
pub local: bool,
/// Optional secret for authenticated supervisor calls
#[serde(skip_serializing_if = "Option::is_none")]
pub secret: Option<String>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
}
/// Parameters for creating a runner
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RunnerCreate {
pub id: u32,
pub pubkey: String,
pub address: IpAddr,
pub topic: String,
pub script_type: ScriptType,
pub local: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub secret: Option<String>,
}
/// Script type supported by a runner
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ScriptType {
Python,
V,
Osis,
Sal,
}
// ==================== Job ====================
/// Parameters for creating a job
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobCreate {
pub id: u32,
pub caller_id: u32,
pub context_id: u32,
pub script: String,
pub script_type: ScriptType,
pub timeout: u64,
#[serde(default)]
pub retries: u8,
#[serde(default)]
pub env_vars: HashMap<String, String>,
#[serde(default)]
pub prerequisites: Vec<u32>,
#[serde(default)]
pub depends: Vec<u32>,
}
// ==================== Flow ====================
/// Flow representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Flow {
pub id: u32,
pub caller_id: u32,
pub context_id: u32,
pub jobs: Vec<u32>,
pub env_vars: HashMap<String, String>,
pub result: HashMap<String, String>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
pub status: FlowStatus,
}
/// Parameters for creating a flow
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FlowCreate {
pub id: u32,
pub caller_id: u32,
pub context_id: u32,
pub jobs: Vec<u32>,
#[serde(default)]
pub env_vars: HashMap<String, String>,
}
/// Flow status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FlowStatus {
Created,
Dispatched,
Started,
Error,
Finished,
}
/// DAG representation of a flow
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FlowDag {
pub flow_id: u32,
pub nodes: Vec<DagNode>,
pub edges: Vec<DagEdge>,
}
/// Node in a DAG
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DagNode {
pub job_id: u32,
pub status: JobStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
/// Edge in a DAG (dependency relationship)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DagEdge {
pub from: u32,
pub to: u32,
}
// ==================== Message ====================
/// Message representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub id: u32,
pub context_id: u32,
pub runner_id: u32,
pub job_id: u32,
pub message_type: MessageType,
pub format: MessageFormatType,
pub payload: String,
pub status: MessageStatus,
pub transport_status: TransportStatus,
pub created_at: Timestamp,
pub updated_at: Timestamp,
}
/// Parameters for creating a message
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageCreate {
pub id: u32,
pub context_id: u32,
pub runner_id: u32,
pub job_id: u32,
pub message_type: MessageType,
pub format: MessageFormatType,
pub payload: String,
}
/// Message type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageType {
JobRun,
JobResult,
JobError,
}
/// Message format
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageFormatType {
JsonRpc,
}
/// Message status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageStatus {
Created,
Sent,
Delivered,
Failed,
}
/// Transport status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TransportStatus {
Pending,
Sent,
Delivered,
Failed,
}