OrchestrationContext

Struct OrchestrationContext 

Source
pub struct OrchestrationContext { /* private fields */ }

Implementations§

Source§

impl OrchestrationContext

Source

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 traces
    • None: Used by standalone/test execution without runtime context
Source

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.

Source

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 identifier
  • execution_id - The current execution number
  • orchestration_name - Name of the orchestration
  • orchestration_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 started

All logs include instance_id, execution_id, orchestration_name for correlation.

Source

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));
Source

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));
Source

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"));
Source

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));
Source

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.

Source

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.

Source

pub fn utcnow(&self) -> impl Future<Output = Result<SystemTime, String>>

Get the current UTC time. Returns a future that resolves to a SystemTime.

§Errors

Returns an error if the system call fails or if the time value cannot be parsed.

§Example
let now = ctx.utcnow().await?;
let deadline = now + Duration::from_secs(3600); // 1 hour from now
Source

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);
        }
        _ => {}
    }
}
Source

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())
Source

pub fn continue_as_new_typed<In: Serialize>( &self, input: &In, ) -> impl Future<Output = Result<String, String>>

Source

pub fn continue_as_new_versioned( &self, version: impl Into<String>, input: impl Into<String>, ) -> impl Future<Output = Result<String, String>>

ContinueAsNew to a specific target version (string is parsed as semver later).

Source§

impl OrchestrationContext

Source

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 select2 with 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)
Source

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.

Source

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).

Source

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.

Source

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!(),
}
Source

pub fn schedule_wait(&self, name: impl Into<String>) -> DurableFuture

Subscribe to an external event by name and return its DurableFuture.

Source

pub fn schedule_wait_typed<T: DeserializeOwned>( &self, name: impl Into<String>, ) -> DurableFuture

Typed external wait adapter pairs with into_event_typed for decoding.

Source

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).

Source

pub fn schedule_sub_orchestration_typed<In: Serialize, Out: DeserializeOwned>( &self, name: impl Into<String>, input: &In, ) -> DurableFuture

Source

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.

Source

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.

Source

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.

Source

pub fn schedule_orchestration_typed<In: Serialize>( &self, name: impl Into<String>, instance: impl Into<String>, input: &In, )

Source

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.

Source

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

Source

pub fn select2(&self, a: DurableFuture, b: DurableFuture) -> SelectFuture

Deterministic select over two futures: returns (winner_index, DurableOutput)

Source

pub fn select(&self, futures: Vec<DurableFuture>) -> SelectFuture

Deterministic select over N futures

Source

pub fn join(&self, futures: Vec<DurableFuture>) -> JoinFuture

Deterministic join over N futures (history order)

Trait Implementations§

Source§

impl Clone for OrchestrationContext

Source§

fn clone(&self) -> OrchestrationContext

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more