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(&self) -> impl Future<Output = Result<SystemTime, String>>
pub fn utcnow(&self) -> impl Future<Output = Result<SystemTime, String>>
Get the current UTC time. Returns a future that resolves to a SystemTime.
§Example
let now = ctx.utcnow().await?;
let deadline = now + Duration::from_secs(3600); // 1 hour from nowSourcepub 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);
}
_ => {}
}
}pub fn continue_as_new(&self, input: impl Into<String>)
pub fn continue_as_new_typed<In: Serialize>(&self, input: &In)
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?;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.
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 moreAuto Trait Implementations§
impl Freeze for OrchestrationContext
impl RefUnwindSafe for OrchestrationContext
impl Send for OrchestrationContext
impl Sync for OrchestrationContext
impl Unpin for OrchestrationContext
impl UnwindSafe for OrchestrationContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more