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}