Skip to main content

openjd_model/job/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright by contributors to this project.
3// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5//! Instantiated job types — the result of `create_job()`.
6//!
7//! These types represent a fully resolved job where all format strings
8//! have been evaluated and template variables substituted. Contrast with
9//! `crate::template` which holds the unresolved template types.
10
11pub mod create_job;
12pub mod step_dependency_graph;
13pub mod step_param_space;
14
15use std::collections::HashMap;
16
17use indexmap::IndexMap;
18use openjd_expr::format_string::FormatString;
19use openjd_expr::symbol_table::SerializedSymbolTable;
20use openjd_expr::ExprValue;
21use openjd_expr::RangeExpr;
22use serde::{Deserialize, Serialize};
23
24use crate::types::{EndOfLine, FileType};
25
26use crate::template::RangeConstraint;
27use crate::types::JobParameterType;
28
29/// A fully instantiated job — all format strings resolved, parameters bound.
30#[derive(Debug, Clone, Serialize)]
31#[serde(rename_all = "camelCase")]
32pub struct Job {
33    pub name: String,
34    pub description: Option<String>,
35    pub extensions: Option<Vec<crate::types::ModelExtension>>,
36    pub parameters: IndexMap<String, JobParameter>,
37    pub steps: Vec<Step>,
38    pub job_environments: Option<Vec<Environment>>,
39}
40
41/// A resolved job parameter (name + type + bound value).
42#[derive(Debug, Clone, Serialize)]
43#[serde(rename_all = "camelCase")]
44pub struct JobParameter {
45    pub name: String,
46    pub param_type: JobParameterType,
47    pub value: ExprValue,
48}
49
50/// A fully instantiated step.
51#[derive(Debug, Clone, Serialize, Deserialize)]
52#[serde(rename_all = "camelCase")]
53pub struct Step {
54    pub name: String,
55    pub description: Option<String>,
56    pub script: StepScript,
57    pub step_environments: Option<Vec<Environment>>,
58    pub parameter_space: Option<StepParameterSpace>,
59    pub host_requirements: Option<HostRequirements>,
60    pub dependencies: Option<Vec<StepDependency>>,
61    /// Complete symbol table at step scope in JSON transport format.
62    /// Contains Param.*, RawParam.*, Job.Name, Step.Name, and step-level let bindings.
63    /// The session deserializes this with PathFormat::host() and layers
64    /// Session.* and Task.* values on top at runtime.
65    #[serde(rename = "resolvedSymTab", skip_serializing_if = "Option::is_none")]
66    pub resolved_symtab: Option<SerializedSymbolTable>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct StepScript {
72    pub let_bindings: Option<Vec<String>>,
73    pub actions: StepActions,
74    pub embedded_files: Option<Vec<EmbeddedFile>>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct StepActions {
80    pub on_run: Action,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct Action {
86    pub command: FormatString,
87    pub args: Option<Vec<FormatString>>,
88    pub timeout: Option<FormatString>,
89    pub cancelation: Option<CancelationMode>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct Environment {
95    pub name: String,
96    pub description: Option<String>,
97    pub script: Option<EnvironmentScript>,
98    pub variables: Option<HashMap<String, FormatString>>,
99    /// Filtered symbol table containing only symbols referenced by this
100    /// environment's format strings (variables, actions, embedded files, let bindings).
101    #[serde(rename = "resolvedSymTab", skip_serializing_if = "Option::is_none")]
102    pub resolved_symtab: Option<SerializedSymbolTable>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106#[serde(rename_all = "camelCase")]
107pub struct EnvironmentScript {
108    pub let_bindings: Option<Vec<String>>,
109    pub actions: EnvironmentActions,
110    pub embedded_files: Option<Vec<EmbeddedFile>>,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub struct EnvironmentActions {
116    pub on_enter: Option<Action>,
117    pub on_exit: Option<Action>,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct EmbeddedFile {
123    pub name: String,
124    #[serde(alias = "type")]
125    pub file_type: FileType,
126    pub filename: Option<FormatString>,
127    pub data: Option<FormatString>,
128    pub runnable: Option<bool>,
129    pub end_of_line: Option<EndOfLine>,
130}
131
132/// §5.3 CancelationMethod — discriminated union on `mode`.
133#[derive(Debug, Clone, Serialize, Deserialize)]
134#[serde(tag = "mode", rename_all = "SCREAMING_SNAKE_CASE", deny_unknown_fields)]
135pub enum CancelationMode {
136    Terminate,
137    #[serde(rename_all = "camelCase")]
138    NotifyThenTerminate {
139        notify_period_in_seconds: Option<FormatString>,
140    },
141}
142
143/// Resolved parameter space with concrete ranges.
144#[derive(Debug, Clone, Serialize, Deserialize)]
145#[serde(rename_all = "camelCase")]
146pub struct StepParameterSpace {
147    pub task_parameter_definitions: IndexMap<String, TaskParameter>,
148    pub combination: Option<String>,
149}
150
151/// A resolved task parameter with concrete range values.
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(rename_all = "camelCase")]
154pub enum TaskParameter {
155    Int {
156        range: TaskParamRange<i64>,
157        chunks: Option<ResolvedChunks>,
158    },
159    Float {
160        range: Vec<f64>,
161    },
162    String {
163        range: Vec<String>,
164    },
165    Path {
166        range: Vec<String>,
167    },
168    ChunkInt {
169        range: TaskParamRange<i64>,
170        chunks: ResolvedChunks,
171    },
172}
173
174/// A resolved range — either a concrete list or a RangeExpr.
175#[derive(Debug, Clone, Serialize, Deserialize)]
176#[serde(
177    rename_all = "camelCase",
178    bound(deserialize = "T: serde::de::DeserializeOwned")
179)]
180pub enum TaskParamRange<T: Serialize> {
181    List(Vec<T>),
182    RangeExpr(RangeExpr),
183}
184
185/// Chunks config with all format strings resolved.
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase")]
188pub struct ResolvedChunks {
189    pub default_task_count: usize,
190    pub target_runtime_seconds: Option<usize>,
191    pub range_constraint: RangeConstraint,
192}
193
194/// Resolved host requirements — no FormatStrings.
195#[derive(Debug, Clone, Serialize, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct HostRequirements {
198    pub amounts: Option<Vec<AmountRequirement>>,
199    pub attributes: Option<Vec<AttributeRequirement>>,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203#[serde(rename_all = "camelCase")]
204pub struct AmountRequirement {
205    pub name: String,
206    pub min: Option<f64>,
207    pub max: Option<f64>,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
211#[serde(rename_all = "camelCase")]
212pub struct AttributeRequirement {
213    pub name: String,
214    pub any_of: Option<Vec<String>>,
215    pub all_of: Option<Vec<String>>,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
219#[serde(rename_all = "camelCase")]
220pub struct StepDependency {
221    pub depends_on: String,
222}