Skip to main content

broccoli_server_sdk/types/
operation.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5/// File source for initial environment setup.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type")]
8pub enum SessionFile {
9    #[serde(rename = "path")]
10    Path { path: String },
11    #[serde(rename = "content")]
12    Content { content: String },
13    #[serde(rename = "blob")]
14    Blob { hash: String },
15}
16
17/// Environment configuration for an operation batch.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Environment {
20    pub id: String,
21    pub files_in: Vec<(String, SessionFile)>,
22}
23
24/// IO target for task stdin/stdout/stderr.
25#[derive(Debug, Clone, Serialize, Deserialize, Default)]
26#[serde(tag = "type")]
27pub enum IOTarget {
28    #[serde(rename = "null")]
29    Null,
30    #[serde(rename = "inherit")]
31    #[default]
32    Inherit,
33    #[serde(rename = "file")]
34    File { path: String },
35    #[serde(rename = "pipe")]
36    Pipe { name: String },
37}
38
39/// IO configuration for task execution.
40#[derive(Debug, Clone, Serialize, Deserialize, Default)]
41pub struct IOConfig {
42    pub stdin: IOTarget,
43    pub stdout: IOTarget,
44    pub stderr: IOTarget,
45}
46
47/// Directory binding options.
48#[derive(Debug, Clone, Default, Serialize, Deserialize)]
49pub struct DirectoryOptions {
50    pub read_write: bool,
51    pub allow_devices: bool,
52    pub no_exec: bool,
53    pub is_filesystem: bool,
54    pub is_tmp: bool,
55    pub no_recursive: bool,
56}
57
58/// Directory binding rule.
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct DirectoryRule {
61    pub inside_path: PathBuf,
62    pub outside_path: Option<PathBuf>,
63    pub options: DirectoryOptions,
64}
65
66/// Environment variable rule.
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub enum EnvRule {
69    Inherit(String),
70    Set(String, String),
71    FullEnv,
72}
73
74/// Resource limits for sandbox execution.
75#[derive(Debug, Clone, Serialize, Deserialize, Default)]
76pub struct ResourceLimits {
77    pub time_limit: Option<f64>,
78    pub wall_time_limit: Option<f64>,
79    pub extra_time: Option<f64>,
80    pub memory_limit: Option<u32>,
81    pub stack_limit: Option<u32>,
82    pub open_files_limit: Option<u32>,
83    pub file_size_limit: Option<u32>,
84    pub process_limit: Option<u32>,
85}
86
87/// Run configuration for a step.
88#[derive(Debug, Clone, Serialize, Deserialize)]
89#[serde(default)]
90pub struct RunOptions {
91    pub resource_limits: ResourceLimits,
92    pub wait: bool,
93    pub as_uid: Option<u32>,
94    pub as_gid: Option<u32>,
95    pub stdin: Option<PathBuf>,
96    pub stdout: Option<PathBuf>,
97    pub stderr: Option<PathBuf>,
98    pub env_rules: Vec<EnvRule>,
99    pub directory_rules: Vec<DirectoryRule>,
100}
101
102impl Default for RunOptions {
103    fn default() -> Self {
104        Self {
105            resource_limits: ResourceLimits {
106                time_limit: None,
107                wall_time_limit: None,
108                extra_time: None,
109                memory_limit: None,
110                stack_limit: None,
111                open_files_limit: None,
112                file_size_limit: None,
113                process_limit: Some(1),
114            },
115            wait: true,
116            as_uid: None,
117            as_gid: None,
118            stdin: None,
119            stdout: None,
120            stderr: None,
121            env_rules: vec![EnvRule::FullEnv],
122            directory_rules: vec![],
123        }
124    }
125}
126
127/// Configuration for step-level caching.
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct StepCacheConfig {
130    pub key_inputs: Vec<String>,
131    pub outputs: Vec<String>,
132}
133
134/// Task definition within an operation.
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct Step {
137    pub id: String,
138    pub env_ref: String,
139    pub argv: Vec<String>,
140    pub conf: RunOptions,
141    pub io: IOConfig,
142    pub collect: Vec<String>,
143    #[serde(default)]
144    pub depends_on: Vec<String>,
145    #[serde(default)]
146    pub cache: Option<StepCacheConfig>,
147}
148
149/// Channel definition for inter-task communication.
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct Channel {
152    pub name: String,
153    pub buffer_size: Option<usize>,
154}
155
156impl Default for Channel {
157    fn default() -> Self {
158        Self {
159            name: String::new(),
160            buffer_size: Some(8192),
161        }
162    }
163}
164
165/// A single operation task dispatched to the worker.
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct OperationTask {
168    pub environments: Vec<Environment>,
169    pub tasks: Vec<Step>,
170    #[serde(default)]
171    pub channels: Vec<Channel>,
172}
173
174/// Result of a worker operation batch.
175#[derive(Debug, Default, Clone, Serialize, Deserialize)]
176pub struct OperationResult {
177    pub success: bool,
178    pub task_results: HashMap<String, TaskExecutionResult>,
179    pub error: Option<String>,
180}
181
182/// Per-task result within an operation batch.
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct TaskExecutionResult {
185    pub task_id: String,
186    pub success: bool,
187    pub sandbox_result: ExecutionResult,
188    #[serde(default)]
189    pub collected_outputs: HashMap<String, String>,
190}
191
192/// Sandbox execution outcome.
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct ExecutionResult {
195    #[serde(default)]
196    pub exit_code: Option<i32>,
197    #[serde(default)]
198    pub signal: Option<i32>,
199    /// CPU time used, in seconds.
200    #[serde(default)]
201    pub time_used: f64,
202    /// Wall-clock time used, in seconds.
203    #[serde(default)]
204    pub wall_time_used: f64,
205    /// Peak memory usage, in kilobytes.
206    #[serde(default)]
207    pub memory_used: Option<u32>,
208    #[serde(default)]
209    pub killed: bool,
210    #[serde(default)]
211    pub cg_oom_killed: bool,
212    #[serde(default)]
213    pub status: String,
214    #[serde(default)]
215    pub message: String,
216    #[serde(default)]
217    pub stdout: String,
218    #[serde(default)]
219    pub stderr: String,
220}
221
222impl Default for ExecutionResult {
223    fn default() -> Self {
224        Self {
225            exit_code: None,
226            signal: None,
227            time_used: 0.0,
228            wall_time_used: 0.0,
229            memory_used: None,
230            killed: false,
231            cg_oom_killed: false,
232            status: "UNKNOWN".to_string(),
233            message: String::new(),
234            stdout: String::new(),
235            stderr: String::new(),
236        }
237    }
238}
239
240pub type SandboxResult = ExecutionResult;