1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//! wfe-core — Core traits, models, builder, executor, and primitives for the WFE
//! persistent workflow engine.
//!
//! # What is WFE?
//!
//! WFE (Workflow Engine) is a trait-based, pluggable workflow engine for Rust.
//! It is designed for long-running, persistent workflows that survive process
//! restarts. You define workflows as code using a fluent builder API, and the
//! executor drives them to completion with support for parallel branches,
//! conditional logic, loops, saga compensation, and event-driven pausing.
//!
//! # Core concepts
//!
//! | Concept | Description |
//! |---------|-------------|
//! | [`StepBody`](crate::traits::step::StepBody) | The trait you implement to define a unit of work. |
//! | [`WorkflowData`](crate::traits::step::WorkflowData) | The data type that flows between steps. Must be serializable. |
//! | [`WorkflowBuilder`](crate::builder::WorkflowBuilder) | Fluent API for composing workflow definitions. |
//! | [`StepBuilder`](crate::builder::StepBuilder) | Per-step configuration (name, error handling, compensation). |
//! | [`WorkflowExecutor`](crate::executor::WorkflowExecutor) | Drives execution: acquires locks, runs steps, persists state. |
//! | [`StepExecutionContext`](crate::traits::step::StepExecutionContext) | Runtime context passed to each step (data, pointers, tokens). |
//! | [`ExecutionResult`](crate::models::ExecutionResult) | What a step returns to control flow (`next`, `branch`, `sleep`, etc.). |
//! | [`WorkflowDefinition`](crate::models::WorkflowDefinition) | The compiled, serializable blueprint of a workflow. |
//! | [`WorkflowInstance`](crate::models::WorkflowInstance) | A running (or persisted) execution of a definition. |
//! | [`ExecutionPointer`](crate::models::ExecutionPointer) | Tracks the position of a single branch of execution. |
//!
//! # Hello workflow
//!
//! ```ignore
//! use async_trait::async_trait;
//! use serde::{Deserialize, Serialize};
//! use wfe_core::builder::WorkflowBuilder;
//! use wfe_core::models::ExecutionResult;
//! use wfe_core::traits::step::{StepBody, StepExecutionContext};
//!
//! #[derive(Debug, Clone, Default, Serialize, Deserialize)]
//! struct OrderData {
//! order_id: String,
//! amount: f64,
//! }
//!
//! #[derive(Default)]
//! struct ValidateOrder;
//!
//! #[async_trait]
//! impl StepBody for ValidateOrder {
//! async fn run(&mut self, ctx: &StepExecutionContext<'_>) -> wfe_core::Result<ExecutionResult> {
//! let data: OrderData = ctx.workflow.data()?;
//! if data.amount <= 0.0 {
//! return Err(wfe_core::WfeError::Execution("amount must be positive".into()));
//! }
//! Ok(ExecutionResult::next())
//! }
//! }
//!
//! #[derive(Default)]
//! struct ProcessPayment;
//!
//! #[async_trait]
//! impl StepBody for ProcessPayment {
//! async fn run(&mut self, _ctx: &StepExecutionContext<'_>) -> wfe_core::Result<ExecutionResult> {
//! println!("Processing payment...");
//! Ok(ExecutionResult::next())
//! }
//! }
//!
//! let definition = WorkflowBuilder::<OrderData>::new()
//! .start_with::<ValidateOrder>()
//! .name("Validate")
//! .then::<ProcessPayment>()
//! .name("Payment")
//! .end_workflow()
//! .build("order-pipeline", 1);
//! ```
//!
//! # Builder patterns
//!
//! The builder supports linear chains, containers, and control flow:
//!
//! - `.then::<S>()` — sequential next step
//! - `.parallel(|b| { b.add_step_typed::<A>("a", None); b.add_step_typed::<B>("b", None); })` — run branches in parallel
//! - `.if_do(|b| { b.add_step_typed::<Then>("then", None); })` — conditional branch
//! - `.while_do(|b| { b.add_step_typed::<LoopBody>("loop", None); })` — loop while condition holds
//! - `.for_each("items", |b| { b.add_step_typed::<ProcessItem>("item", None); })` — iterate over a collection
//! - `.saga(|b| { b.add_step_typed::<Do>("do", None); }).compensate_with::<Undo>()` — saga with compensation
//! - `.wait_for("event_name", "event_key")` — suspend until an external event arrives
//! - `.delay(Duration::from_secs(30))` — pause for a fixed duration
//! - `.then_fn(|| { println!("inline"); ExecutionResult::next() })` — inline closure step
//!
//! # Execution model
//!
//! 1. You build a [`WorkflowDefinition`](crate::models::WorkflowDefinition) using the builder API.
//! 2. You register the definition and all step types with a `WorkflowHost` (from the `wfe` crate).
//! 3. The host creates a [`WorkflowInstance`](crate::models::WorkflowInstance), persists it, and queues it for execution.
//! 4. The [`WorkflowExecutor`](crate::executor::WorkflowExecutor) picks up the instance, acquires a distributed lock, and runs each active [`ExecutionPointer`](crate::models::ExecutionPointer).
//! 5. After each step, the executor processes the [`ExecutionResult`](crate::models::ExecutionResult) — branching, suspending, or completing pointers — and persists the new state.
//! 6. The lock is released, and the instance is re-queued if there is more work to do.
//!
//! This means workflows are **durable**: if the process crashes after step 3, the next executor invocation will resume from step 4 because the pointer state was persisted.
//!
//! # Primitives
//!
//! Built-in control-flow steps live in [`primitives`]:
//!
//! | Primitive | Purpose |
//! |-----------|---------|
//! | [`IfStep`](primitives::if_step::IfStep) | Conditional branching with `then`/`else` children |
//! | [`WhileStep`](primitives::while_step::WhileStep) | Loop while a condition evaluates to `true` |
//! | [`ForEachStep`](primitives::foreach_step::ForEachStep) | Iterate over a JSON array in workflow data |
//! | [`SequenceStep`](primitives::sequence::SequenceStep) | Parallel branch container (all children run concurrently) |
//! | [`DecideStep`](primitives::decide::DecideStep) | Multi-way branch (switch/case style) |
//! | [`DelayStep`](primitives::delay::DelayStep) | Pause execution for a duration |
//! | [`ScheduleStep`](primitives::schedule::ScheduleStep) | Resume at a specific wall-clock time |
//! | [`WaitForStep`](primitives::wait_for::WaitForStep) | Suspend until an external event is published |
//! | [`SagaContainerStep`](primitives::saga_container::SagaContainerStep) | Transaction-like container with compensation on failure |
//! | [`RecurStep`](primitives::recur::RecurStep) | Recurring/periodic execution |
//! | [`PollEndpointStep`](primitives::poll_endpoint::PollEndpointStep) | Poll an HTTP endpoint until a condition is met |
//! | [`SubWorkflowStep`](primitives::sub_workflow::SubWorkflowStep) | Start a child workflow and wait for it to complete |
//! | [`EndStep`](primitives::end_step::EndStep) | Explicit workflow termination |
//!
//! # Error handling
//!
//! Steps return [`ExecutionResult`](crate::models::ExecutionResult) which can signal:
//! - [`ExecutionResult::next()`](crate::models::ExecutionResult::next) — continue to the next step
//! - [`ExecutionResult::outcome(v)`](crate::models::ExecutionResult::outcome) — follow a named outcome branch
//! - [`ExecutionResult::sleep(d)`](crate::models::ExecutionResult::sleep) — pause execution (used by `DelayStep`)
//! - `Err(WfeError::Execution(...))` — mark the pointer as failed
//! - [`ExecutionResult::persist(d)`](crate::models::ExecutionResult::persist) — mark the pointer as complete
//!
//! When a step fails, the executor checks the step's [`ErrorBehavior`](models::ErrorBehavior):
//! - `Retry { interval, max_retries }` — retry with backoff
//! - `Suspend` — pause the workflow for manual intervention
//! - `CompensateThenRetry` — run the compensation step, then retry
//! - `CompensateThenSuspend` — run compensation, then suspend
//!
//! # Feature flags
//!
//! | Feature | Description |
//! |---------|-------------|
//! | `test-support` | In-memory persistence, lock, and queue providers for unit testing |
//! | `otel` | OpenTelemetry tracing integration |
//!
//! # Testing
//!
//! ```sh
//! cargo test -p wfe-core
//! ```
//!
//! No external dependencies required.
/// Fluent builder API for composing workflow definitions.
///
/// See [`WorkflowBuilder`](crate::builder::WorkflowBuilder) for the main entry point and
/// [`StepBuilder`](crate::builder::StepBuilder) for per-step configuration.
/// Error types and the [`Result`](error::Result) alias used throughout WFE.
/// The workflow executor and supporting infrastructure.
///
/// [`WorkflowExecutor`](executor::WorkflowExecutor) is the heart of the engine.
/// It acquires locks, loads instances, runs active pointers, and persists state.
/// Data models for workflows, instances, pointers, events, and execution results.
/// Built-in control-flow primitives (if, while, foreach, saga, etc.).
/// Core traits that define the plugin architecture.
///
/// Implement these traits to provide persistence, locking, queuing, lifecycle
/// events, search, logging, and service provisioning.
/// In-memory test doubles for every provider trait.
/// Artifact volume abstraction for distributed workflow execution.
/// Local filesystem artifact store (OCI Image Layout).
pub use ;
pub use ;
pub use ;