Skip to main content

RuntimeOptions

Struct RuntimeOptions 

Source
pub struct RuntimeOptions {
Show 19 fields pub dispatcher_min_poll_interval: Duration, pub dispatcher_long_poll_timeout: Duration, pub orchestration_concurrency: usize, pub worker_concurrency: usize, pub orchestrator_lock_timeout: Duration, pub orchestrator_lock_renewal_buffer: Duration, pub worker_lock_timeout: Duration, pub worker_lock_renewal_buffer: Duration, pub observability: ObservabilityConfig, pub unregistered_backoff: UnregisteredBackoffConfig, pub max_attempts: u32, pub activity_cancellation_grace_period: Duration, pub supported_replay_versions: Option<SemverRange>, pub session_lock_timeout: Duration, pub session_lock_renewal_buffer: Duration, pub session_idle_timeout: Duration, pub session_cleanup_interval: Duration, pub max_sessions_per_runtime: usize, pub worker_node_id: Option<String>,
}
Expand description

Configuration options for the Runtime.

§Example

let options = RuntimeOptions {
    orchestration_concurrency: 4,
    worker_concurrency: 8,
    dispatcher_min_poll_interval: Duration::from_millis(25), // Polling backoff when queues idle
    dispatcher_long_poll_timeout: Duration::from_secs(30),   // Long polling timeout
    orchestrator_lock_timeout: Duration::from_secs(10),      // Orchestration turns retry after 10s
    worker_lock_timeout: Duration::from_secs(300),        // Activities retry after 5 minutes
    worker_lock_renewal_buffer: Duration::from_secs(30),  // Renew worker locks 30s early
    observability: ObservabilityConfig {
        log_format: LogFormat::Compact,
       log_level: "info".to_string(),
        ..Default::default()
    },
    ..Default::default()
};

Fields§

§dispatcher_min_poll_interval: Duration

Minimum polling cycle duration when idle.

If a provider returns ‘None’ (no work) faster than this duration, the dispatcher will sleep for the remainder of the time. This prevents hot loops for providers that do not support long polling or return early.

Default: 100ms (10 Hz)

§dispatcher_long_poll_timeout: Duration

Maximum time to wait for work inside the provider (Long Polling).

Only used if the provider supports long polling.

Default: 30 seconds

§orchestration_concurrency: usize

Number of concurrent orchestration workers. Each worker can process one orchestration turn at a time. Higher values = more parallel orchestration execution. Default: 2

§worker_concurrency: usize

Number of concurrent worker dispatchers. Each worker can execute one activity at a time. Higher values = more parallel activity execution. Default: 2

§orchestrator_lock_timeout: Duration

Lock timeout for orchestrator queue items. When an orchestration message is dequeued, it’s locked for this duration. Orchestration turns are typically fast (milliseconds), so a shorter timeout is appropriate. If processing doesn’t complete within this time, the lock expires and the message is retried. Default: 5 seconds

§orchestrator_lock_renewal_buffer: Duration

Buffer time before orchestration lock expiration to trigger renewal.

Lock renewal strategy:

  • If orchestrator_lock_timeout ≥ 15s: renew at (timeout - orchestrator_lock_renewal_buffer)
  • If orchestrator_lock_timeout < 15s: renew at 0.5 × timeout (buffer ignored)

Default: 2 seconds

§worker_lock_timeout: Duration

Lock timeout for worker queue items (activities). When an activity is dequeued, it’s locked for this duration. Activities can be long-running (minutes), so a longer timeout is appropriate. If processing doesn’t complete within this time, the lock expires and the activity is retried. Higher values = more tolerance for long-running activities. Lower values = faster retry on failures, but may timeout legitimate work. Default: 30 seconds

§worker_lock_renewal_buffer: Duration

Buffer time before lock expiration to trigger renewal.

Lock renewal strategy:

  • If worker_lock_timeout ≥ 15s: renew at (timeout - worker_lock_renewal_buffer)
  • If worker_lock_timeout < 15s: renew at 0.5 × timeout (buffer ignored)

Example with default values (timeout=30s, buffer=5s):

  • Initial lock: expires at T+30s
  • First renewal: at T+25s (30-5), extends to T+55s
  • Second renewal: at T+50s (55-5), extends to T+80s

Example with short timeout (timeout=10s, buffer ignored):

  • Initial lock: expires at T+10s
  • First renewal: at T+5s (10*0.5), extends to T+15s
  • Second renewal: at T+10s (15*0.5), extends to T+20s

Default: 5 seconds

§observability: ObservabilityConfig

Observability configuration for metrics and logging. Requires the observability feature flag for full functionality. Default: Disabled with basic logging

§unregistered_backoff: UnregisteredBackoffConfig

Configuration for backoff when encountering unregistered orchestrations/activities.

During rolling deployments, work items for unregistered handlers are abandoned with exponential backoff instead of immediately failing. This allows the runtime to wait for the handler to be registered on upgraded nodes.

Default: 1s base delay, 60s max delay

§max_attempts: u32

Maximum fetch attempts before a message is considered poison.

After this many fetch attempts, the runtime will immediately fail the orchestration/activity with a Poison error instead of processing.

Default: 10

§activity_cancellation_grace_period: Duration

Grace period for activity cancellation.

When an orchestration reaches a terminal state, in-flight activities are notified via their cancellation token. This setting controls how long to wait for activities to complete gracefully before aborting the activity task to free worker capacity.

After this grace period, if the activity has not completed:

  • The activity task is aborted (JoinHandle::abort())
  • The worker queue message is dropped without notifying the orchestrator
  • A warning is logged

Note: Child tasks/threads spawned by the activity that do not observe the cancellation token may outlive the abort (user responsibility).

Default: 10 seconds

§supported_replay_versions: Option<SemverRange>

Override the replay-engine version range used for capability filtering.

By default, the runtime uses >=0.0.0, <=CURRENT_BUILD_VERSION, meaning it can replay any execution pinned at or below its own semver. This is correct for most deployments since replay engines are backward-compatible.

Set this to change the range for advanced scenarios:

  • Narrowing: Restrict a node to only process a specific version band (e.g., >=1.0.0, <=1.9.999 in a mixed-version cluster).
  • Widening to drain stuck items: Set a wide range like >=0.0.0, <=99.0.0 to fetch orchestrations pinned at any version. Items with unknown event types will fail at provider-level deserialization (never reaching the replay engine) and remain in the queue with escalating attempt_count.

Default: None (uses >=0.0.0, <=CURRENT_BUILD_VERSION)

§session_lock_timeout: Duration

Lock timeout for session heartbeat lease. Controls crash recovery speed — if a worker dies, its sessions become claimable after this duration. Default: 30 seconds

§session_lock_renewal_buffer: Duration

Buffer time before session lock expiration to trigger renewal. Uses the same formula as worker_lock_renewal_buffer. Default: 5 seconds

§session_idle_timeout: Duration

How long a session stays pinned after the last activity is fetched, renewed, or completed. The session renewal thread stops heartbeating idle sessions, so their locks naturally expire. Default: 5 minutes

§session_cleanup_interval: Duration

How often orphaned session rows are swept from the sessions table. Runs on the same background thread as session lock renewal. Default: 5 minutes

§max_sessions_per_runtime: usize

Maximum number of distinct sessions this runtime will own concurrently, spanning all worker_concurrency slots.

A single SessionTracker is shared across every worker slot in this runtime. When distinct_count() reaches this limit, all slots stop claiming new sessions (fetch switches to non-session mode) until an in-flight session activity completes and frees a session slot.

Session activities and non-session activities share the same worker_concurrency slots. Default: 10

§worker_node_id: Option<String>

Stable worker identity for session ownership. If set, used directly as the session worker_id for session claims — all worker_concurrency slots share this single identity, so any idle slot can serve any session owned by this runtime (no head-of-line blocking). Also allows a restarted worker to reclaim its sessions without waiting for lock expiry. Example: Kubernetes StatefulSet pod name. If None, uses ephemeral per-slot identity (work-{idx}-{runtime_id}); sessions are pinned per-slot and cannot survive restarts. Note: Logging/tracing always includes the per-slot work-{idx}-{node_id} format regardless of this setting. Default: None

Trait Implementations§

Source§

impl Clone for RuntimeOptions

Source§

fn clone(&self) -> RuntimeOptions

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
Source§

impl Debug for RuntimeOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RuntimeOptions

Source§

fn default() -> Self

Returns the “default value” for a type. 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