Skip to main content

orca_core/
runtime.rs

1//! Core runtime abstraction for workload execution.
2
3use std::collections::HashMap;
4use std::pin::Pin;
5use std::time::Duration;
6
7use async_trait::async_trait;
8use tokio::io::AsyncRead;
9
10use crate::error::Result;
11use crate::types::{ResourceStats, WorkloadSpec, WorkloadStatus};
12
13/// Opaque handle returned by a runtime after creating a workload.
14#[derive(Debug, Clone)]
15pub struct WorkloadHandle {
16    /// Runtime-specific identifier (container ID, Wasm instance ID, etc.)
17    pub runtime_id: String,
18    /// Human-friendly name.
19    pub name: String,
20    /// Runtime-specific metadata (e.g., host_port, container_ip).
21    pub metadata: HashMap<String, String>,
22}
23
24/// Options for log retrieval.
25#[derive(Debug, Clone, Default)]
26pub struct LogOpts {
27    /// Follow log output (stream).
28    pub follow: bool,
29    /// Number of recent lines to return.
30    pub tail: Option<u64>,
31    /// Only return logs since this timestamp.
32    pub since: Option<chrono::DateTime<chrono::Utc>>,
33    /// Include timestamps in log output.
34    pub timestamps: bool,
35}
36
37/// Result of executing a command inside a workload.
38#[derive(Debug)]
39pub struct ExecResult {
40    /// Process exit code.
41    pub exit_code: i32,
42    /// Standard output bytes.
43    pub stdout: Vec<u8>,
44    /// Standard error bytes.
45    pub stderr: Vec<u8>,
46}
47
48/// A stream of log bytes.
49pub type LogStream = Pin<Box<dyn AsyncRead + Send>>;
50
51/// The core runtime abstraction. Both container and Wasm runtimes implement this.
52#[async_trait]
53pub trait Runtime: Send + Sync + 'static {
54    /// Human-readable name of this runtime (e.g., "container", "wasm").
55    fn name(&self) -> &str;
56
57    /// Create a new workload from the given spec. Does not start it.
58    async fn create(&self, spec: &WorkloadSpec) -> Result<WorkloadHandle>;
59
60    /// Start a previously created workload.
61    async fn start(&self, handle: &WorkloadHandle) -> Result<()>;
62
63    /// Stop a running workload, waiting up to `timeout` for graceful shutdown.
64    async fn stop(&self, handle: &WorkloadHandle, timeout: Duration) -> Result<()>;
65
66    /// Remove a stopped workload and clean up resources.
67    async fn remove(&self, handle: &WorkloadHandle) -> Result<()>;
68
69    /// Get the current status of a workload.
70    async fn status(&self, handle: &WorkloadHandle) -> Result<WorkloadStatus>;
71
72    /// Stream logs from a workload.
73    async fn logs(&self, handle: &WorkloadHandle, opts: &LogOpts) -> Result<LogStream>;
74
75    /// Execute a command inside a running workload.
76    async fn exec(&self, handle: &WorkloadHandle, cmd: &[String]) -> Result<ExecResult>;
77
78    /// Get current resource usage stats.
79    async fn stats(&self, handle: &WorkloadHandle) -> Result<ResourceStats>;
80
81    /// Resolve the host-accessible port for a workload after it has been started.
82    ///
83    /// Returns `None` if the runtime does not expose ports or the workload has no port mapping.
84    /// Default implementation returns `None`.
85    async fn resolve_host_port(
86        &self,
87        handle: &WorkloadHandle,
88        _container_port: u16,
89    ) -> Result<Option<u16>> {
90        Ok(handle
91            .metadata
92            .get("host_port")
93            .and_then(|p| p.parse().ok()))
94    }
95}