feat(wfe-core): add typed workflow schema system

SchemaType enum with inline syntax parsing: "string", "string?",
"list<number>", "map<string>", nested generics. WorkflowSchema
validates inputs/outputs against type declarations at both compile
time and runtime. 39 tests for parse and validate paths.
This commit is contained in:
2026-03-26 14:12:51 +00:00
parent 0317c6adea
commit a3211552a5
8 changed files with 998 additions and 30 deletions

View File

@@ -68,6 +68,7 @@ mod tests {
step: &step,
workflow: &instance,
cancellation_token: tokio_util::sync::CancellationToken::new(),
host_context: None,
};
mw.pre_step(&ctx).await.unwrap();
}
@@ -86,6 +87,7 @@ mod tests {
step: &step,
workflow: &instance,
cancellation_token: tokio_util::sync::CancellationToken::new(),
host_context: None,
};
let result = ExecutionResult::next();
mw.post_step(&ctx, &result).await.unwrap();

View File

@@ -17,4 +17,4 @@ pub use persistence::{
pub use queue::QueueProvider;
pub use registry::WorkflowRegistry;
pub use search::{Page, SearchFilter, SearchIndex, WorkflowSearchResult};
pub use step::{StepBody, StepExecutionContext, WorkflowData};
pub use step::{HostContext, StepBody, StepExecutionContext, WorkflowData};

View File

@@ -11,8 +11,18 @@ pub trait WorkflowData: Serialize + DeserializeOwned + Send + Sync + Clone + 'st
/// Blanket implementation: any type satisfying the bounds is WorkflowData.
impl<T> WorkflowData for T where T: Serialize + DeserializeOwned + Send + Sync + Clone + 'static {}
/// Context for steps that need to interact with the workflow host.
/// Implemented by WorkflowHost to allow steps like SubWorkflow to start child workflows.
pub trait HostContext: Send + Sync {
fn start_workflow(
&self,
definition_id: &str,
version: u32,
data: serde_json::Value,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<String>> + Send + '_>>;
}
/// Context available to a step during execution.
#[derive(Debug)]
pub struct StepExecutionContext<'a> {
/// The current item when iterating (ForEach).
pub item: Option<&'a serde_json::Value>,
@@ -26,6 +36,22 @@ pub struct StepExecutionContext<'a> {
pub workflow: &'a WorkflowInstance,
/// Cancellation token.
pub cancellation_token: tokio_util::sync::CancellationToken,
/// Host context for starting child workflows. None if not available.
pub host_context: Option<&'a dyn HostContext>,
}
// Manual Debug impl since dyn HostContext is not Debug.
impl<'a> std::fmt::Debug for StepExecutionContext<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StepExecutionContext")
.field("item", &self.item)
.field("execution_pointer", &self.execution_pointer)
.field("persistence_data", &self.persistence_data)
.field("step", &self.step)
.field("workflow", &self.workflow)
.field("host_context", &self.host_context.is_some())
.finish()
}
}
/// The core unit of work in a workflow. Each step implements this trait.