pub struct OrchestrationContext { /* private fields */ }Implementations§
Source§impl OrchestrationContext
impl OrchestrationContext
Sourcepub fn new(
history: Vec<Event>,
execution_id: u64,
instance_id: String,
orchestration_name: Option<String>,
orchestration_version: Option<String>,
worker_id: Option<String>,
) -> Self
pub fn new( history: Vec<Event>, execution_id: u64, instance_id: String, orchestration_name: Option<String>, orchestration_version: Option<String>, worker_id: Option<String>, ) -> Self
Construct a new context from an existing history vector.
§Parameters
worker_id- Optional dispatcher worker ID for logging correlation.Some(id): Used by runtime dispatchers to include worker_id in tracesNone: Used by standalone/test execution without runtime context
Sourcepub fn is_logging_enabled(&self) -> bool
pub fn is_logging_enabled(&self) -> bool
Indicates whether logging is enabled for the current poll. This is flipped on when a decision is recorded to minimize log noise.
Sourcepub fn trace(&self, level: impl Into<String>, message: impl Into<String>)
pub fn trace(&self, level: impl Into<String>, message: impl Into<String>)
Emit a structured trace entry with automatic context correlation.
Creates a system call event for deterministic replay and logs to tracing. The log entry automatically includes correlation fields:
instance_id- The orchestration instance identifierexecution_id- The current execution numberorchestration_name- Name of the orchestrationorchestration_version- Semantic version
§Determinism
This method is replay-safe: logs are only emitted on first execution,
not during replay. A SystemCall event is created in history to ensure
deterministic replay behavior.
§Example
ctx.trace("INFO", "Processing started");
ctx.trace("WARN", format!("Retry attempt: {}", 3));
ctx.trace("ERROR", "Payment validation failed");§Output
2024-10-30T10:15:23.456Z INFO duroxide::orchestration [order-123] Processing startedAll logs include instance_id, execution_id, orchestration_name for correlation.
Sourcepub fn trace_info(&self, message: impl Into<String>)
pub fn trace_info(&self, message: impl Into<String>)
Convenience wrapper for INFO level tracing.
Logs with INFO level and includes instance context automatically.
§Example
ctx.trace_info("Order validation successful");
ctx.trace_info(format!("Processing {} items", 42));Sourcepub fn trace_warn(&self, message: impl Into<String>)
pub fn trace_warn(&self, message: impl Into<String>)
Convenience wrapper for WARN level tracing.
Logs with WARN level and includes instance context automatically.
§Example
ctx.trace_warn("Retrying failed operation");
ctx.trace_warn(format!("Attempt {}/5", 3));Sourcepub fn trace_error(&self, message: impl Into<String>)
pub fn trace_error(&self, message: impl Into<String>)
Convenience wrapper for ERROR level tracing.
Logs with ERROR level and includes instance context automatically.
§Example
ctx.trace_error("Payment processing failed");
ctx.trace_error(format!("Critical error: {}", "timeout"));Sourcepub fn trace_debug(&self, message: impl Into<String>)
pub fn trace_debug(&self, message: impl Into<String>)
Convenience wrapper for DEBUG level tracing.
Logs with DEBUG level and includes instance context automatically.
§Example
ctx.trace_debug("Detailed state information");
ctx.trace_debug(format!("Variable value: {:?}", 42));Sourcepub fn new_guid(&self) -> impl Future<Output = Result<String, String>>
pub fn new_guid(&self) -> impl Future<Output = Result<String, String>>
Generate a new deterministic GUID. Returns a future that resolves to a String GUID.
Sourcepub fn new_guid_future(&self) -> DurableFuture ⓘ
pub fn new_guid_future(&self) -> DurableFuture ⓘ
Generate a new deterministic GUID as a DurableFuture. This variant returns a DurableFuture that can be used with join/select.
Sourcepub fn utcnow_future(&self) -> DurableFuture ⓘ
pub fn utcnow_future(&self) -> DurableFuture ⓘ
Get the current UTC time as a DurableFuture. This variant returns a DurableFuture that can be used with join/select.
Note: When awaited, this returns a String representation of milliseconds.
For direct use, prefer utcnow() which returns SystemTime.
§Example
let time_future = ctx.utcnow_future();
let activity_future = ctx.schedule_activity("Task", "input");
let results = ctx.join(vec![time_future, activity_future]).await;
for result in results {
match result {
DurableOutput::Activity(Ok(s)) => {
// Parse timestamp string to SystemTime
let ms: u64 = s.parse().map_err(|e: std::num::ParseIntError| e.to_string())?;
let time = UNIX_EPOCH + Duration::from_millis(ms);
}
_ => {}
}
}Sourcepub fn continue_as_new(
&self,
input: impl Into<String>,
) -> impl Future<Output = Result<String, String>>
pub fn continue_as_new( &self, input: impl Into<String>, ) -> impl Future<Output = Result<String, String>>
Continue the current execution as a new execution with fresh input.
This terminates the current execution and starts a new execution with the provided input.
Returns a future that never resolves, ensuring code after await is unreachable.
§Example
let n: u32 = 0;
if n < 2 {
return ctx.continue_as_new("next_input").await; // Execution terminates here
// This code is unreachable - compiler will warn
}
Ok("completed".to_string())pub fn continue_as_new_typed<In: Serialize>( &self, input: &In, ) -> impl Future<Output = Result<String, String>>
Source§impl OrchestrationContext
impl OrchestrationContext
Sourcepub fn schedule_activity(
&self,
name: impl Into<String>,
input: impl Into<String>,
) -> DurableFuture ⓘ
pub fn schedule_activity( &self, name: impl Into<String>, input: impl Into<String>, ) -> DurableFuture ⓘ
Schedule an activity and return a DurableFuture correlated to it.
Activities should be single-purpose execution units. Pull multi-step logic and control flow into orchestrations.
⚠️ IMPORTANT: You MUST call .into_activity().await, not just .await!
§Examples
// ✅ CORRECT: Schedule and await activity
let result = ctx.schedule_activity("ProcessData", "input").into_activity().await?;
// ❌ WRONG: This won't compile!
// let result = ctx.schedule_activity("ProcessData", "input").await; // Missing .into_activity()!§Good Activity Examples
- Database queries
- HTTP API calls (can include retries)
- File operations
- Data transformations
- VM provisioning (can poll for readiness internally)
- Any single-purpose work unit
§What NOT to put in activities
- Multi-step business logic (pull into orchestration)
- Control flow decisions (if/match on business rules)
- Pure delays with no work (use
schedule_timer()instead) - Timeouts for orchestration coordination (use
select2with timers)
§Note on Sleep/Polling in Activities
Activities CAN sleep or poll as part of their work:
- ✅ Provisioning a resource and polling for readiness
- ✅ Retrying an external API with backoff
- ✅ Waiting for async operation to complete
- ❌ Activity that ONLY sleeps (use orchestration timer instead)
Sourcepub fn schedule_activity_typed<In: Serialize, Out: DeserializeOwned>(
&self,
name: impl Into<String>,
input: &In,
) -> DurableFuture ⓘ
pub fn schedule_activity_typed<In: Serialize, Out: DeserializeOwned>( &self, name: impl Into<String>, input: &In, ) -> DurableFuture ⓘ
Typed helper that serializes input and later decodes output via into_activity_typed.
Sourcepub async fn schedule_activity_with_retry(
&self,
name: impl Into<String>,
input: impl Into<String>,
policy: RetryPolicy,
) -> Result<String, String>
pub async fn schedule_activity_with_retry( &self, name: impl Into<String>, input: impl Into<String>, policy: RetryPolicy, ) -> Result<String, String>
Schedule activity with automatic retry on failure.
Retry behavior:
- Retries on activity errors up to
policy.max_attempts - Timeouts are NOT retried - if any attempt times out, returns error immediately
- Only application errors trigger retry logic
Timeout behavior (if policy.total_timeout is set):
- Each activity attempt is raced against the timeout
- If the timeout fires before the activity completes → returns timeout error (no retry)
- If the activity fails with an error before timeout → retry according to policy
§Example
// Simple retry with defaults (no timeout)
let result = ctx.schedule_activity_with_retry(
"CallAPI",
"request",
RetryPolicy::new(3),
).await?;
// Retry with per-attempt timeout and custom backoff
let result = ctx.schedule_activity_with_retry(
"CallAPI",
"request",
RetryPolicy::new(5)
.with_timeout(Duration::from_secs(30)) // 30s per attempt
.with_backoff(BackoffStrategy::Fixed { delay: Duration::from_secs(1) }),
).await?;§Errors
Returns an error if all retry attempts fail or if a timeout occurs (timeouts are not retried).
Sourcepub async fn schedule_activity_with_retry_typed<In: Serialize, Out: DeserializeOwned>(
&self,
name: impl Into<String>,
input: &In,
policy: RetryPolicy,
) -> Result<Out, String>
pub async fn schedule_activity_with_retry_typed<In: Serialize, Out: DeserializeOwned>( &self, name: impl Into<String>, input: &In, policy: RetryPolicy, ) -> Result<Out, String>
Typed variant of schedule_activity_with_retry.
Serializes input once and deserializes the successful result.
§Errors
Returns an error if all retry attempts fail, if a timeout occurs, if input serialization fails, or if result deserialization fails.
Sourcepub fn schedule_timer(&self, delay: Duration) -> DurableFuture ⓘ
pub fn schedule_timer(&self, delay: Duration) -> DurableFuture ⓘ
Schedule a timer for delays, timeouts, and scheduled execution.
Use this for any time-based waiting, NOT activities with sleep!
⚠️ IMPORTANT: You MUST call .into_timer().await, not just .await!
§Examples
// ✅ CORRECT: Wait 5 seconds
ctx.schedule_timer(Duration::from_secs(5)).into_timer().await;
// ❌ WRONG: This won't compile!
// ctx.schedule_timer(Duration::from_secs(5)).await; // Missing .into_timer()!
// Timeout pattern
let work = ctx.schedule_activity("LongTask", "input");
let timeout = ctx.schedule_timer(Duration::from_secs(30)); // 30 second timeout
let (winner, _) = ctx.select2(work, timeout).await;
match winner {
0 => println!("Work completed"),
1 => println!("Timed out"),
_ => unreachable!(),
}Sourcepub fn schedule_wait(&self, name: impl Into<String>) -> DurableFuture ⓘ
pub fn schedule_wait(&self, name: impl Into<String>) -> DurableFuture ⓘ
Subscribe to an external event by name and return its DurableFuture.
Sourcepub fn schedule_wait_typed<T: DeserializeOwned>(
&self,
name: impl Into<String>,
) -> DurableFuture ⓘ
pub fn schedule_wait_typed<T: DeserializeOwned>( &self, name: impl Into<String>, ) -> DurableFuture ⓘ
Typed external wait adapter pairs with into_event_typed for decoding.
Sourcepub fn schedule_sub_orchestration(
&self,
name: impl Into<String>,
input: impl Into<String>,
) -> DurableFuture ⓘ
pub fn schedule_sub_orchestration( &self, name: impl Into<String>, input: impl Into<String>, ) -> DurableFuture ⓘ
Schedule a sub-orchestration by name with deterministic child instance id derived from parent context and event_id (determined during first poll).
pub fn schedule_sub_orchestration_typed<In: Serialize, Out: DeserializeOwned>( &self, name: impl Into<String>, input: &In, ) -> DurableFuture ⓘ
Sourcepub fn schedule_sub_orchestration_versioned(
&self,
name: impl Into<String>,
version: Option<String>,
input: impl Into<String>,
) -> DurableFuture ⓘ
pub fn schedule_sub_orchestration_versioned( &self, name: impl Into<String>, version: Option<String>, input: impl Into<String>, ) -> DurableFuture ⓘ
Versioned sub-orchestration start (string I/O). If version is None, registry policy is used.
Sourcepub fn schedule_sub_orchestration_versioned_typed<In: Serialize, Out: DeserializeOwned>(
&self,
name: impl Into<String>,
version: Option<String>,
input: &In,
) -> DurableFuture ⓘ
pub fn schedule_sub_orchestration_versioned_typed<In: Serialize, Out: DeserializeOwned>( &self, name: impl Into<String>, version: Option<String>, input: &In, ) -> DurableFuture ⓘ
Versioned typed sub-orchestration.
Sourcepub fn schedule_orchestration(
&self,
name: impl Into<String>,
instance: impl Into<String>,
input: impl Into<String>,
)
pub fn schedule_orchestration( &self, name: impl Into<String>, instance: impl Into<String>, input: impl Into<String>, )
Schedule a detached orchestration with an explicit instance id. The runtime will prefix this with the parent instance to ensure global uniqueness.
pub fn schedule_orchestration_typed<In: Serialize>( &self, name: impl Into<String>, instance: impl Into<String>, input: &In, )
Sourcepub fn schedule_orchestration_versioned(
&self,
name: impl Into<String>,
version: Option<String>,
instance: impl Into<String>,
input: impl Into<String>,
)
pub fn schedule_orchestration_versioned( &self, name: impl Into<String>, version: Option<String>, instance: impl Into<String>, input: impl Into<String>, )
Versioned detached orchestration start (string I/O). If version is None, registry policy is used for the child.
pub fn schedule_orchestration_versioned_typed<In: Serialize>( &self, name: impl Into<String>, version: Option<String>, instance: impl Into<String>, input: &In, )
Source§impl OrchestrationContext
impl OrchestrationContext
Sourcepub fn select2(&self, a: DurableFuture, b: DurableFuture) -> SelectFuture ⓘ
pub fn select2(&self, a: DurableFuture, b: DurableFuture) -> SelectFuture ⓘ
Deterministic select over two futures: returns (winner_index, DurableOutput)
Sourcepub fn select(&self, futures: Vec<DurableFuture>) -> SelectFuture ⓘ
pub fn select(&self, futures: Vec<DurableFuture>) -> SelectFuture ⓘ
Deterministic select over N futures
Sourcepub fn join(&self, futures: Vec<DurableFuture>) -> JoinFuture ⓘ
pub fn join(&self, futures: Vec<DurableFuture>) -> JoinFuture ⓘ
Deterministic join over N futures (history order)
Trait Implementations§
Source§impl Clone for OrchestrationContext
impl Clone for OrchestrationContext
Source§fn clone(&self) -> OrchestrationContext
fn clone(&self) -> OrchestrationContext
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more