Skip to main content

temporalio_sdk/
runtime.rs

1//! Runtime configuration and low-level Core worker building blocks.
2//!
3//! These types are grouped here to keep Core-specific configuration separate from the SDK's
4//! primary workflow and activity APIs. Create a [`crate::Runtime`] before connecting a client,
5//! then pass it to [`crate::Worker::new`].
6
7use std::{
8    ops::{Deref, DerefMut},
9    time::Duration,
10};
11
12use temporalio_common::telemetry::{TelemetryInstance, TelemetryOptions};
13use temporalio_sdk_core::{CoreRuntime, RuntimeOptions as CoreRuntimeOptions};
14
15pub use temporalio_sdk_core::{
16    ActivitySlotKind, FixedSizeSlotSupplier, LocalActivitySlotKind, NexusSlotKind, PollerBehavior,
17    ResourceBasedSlotsOptions, ResourceBasedSlotsOptionsBuilder, ResourceBasedTuner,
18    ResourceBasedTunerConfig, ResourceController, ResourceSlotOptions, SlotInfo, SlotInfoTrait,
19    SlotKind, SlotKindType, SlotMarkUsedContext, SlotReleaseContext, SlotReservationContext,
20    SlotSupplier, SlotSupplierOptions, SlotSupplierPermit, TokioRuntimeBuilder, TunerBuilder,
21    TunerHolder, TunerHolderOptions, TunerHolderOptionsBuilder, Worker as CoreWorker, WorkerConfig,
22    WorkerConfigBuilder, WorkerTuner, WorkerVersioningStrategy, WorkflowErrorType,
23    WorkflowSlotKind, init_replay_worker, replay,
24};
25
26/// Configuration for the Rust SDK runtime. Construct with [`RuntimeOptions::builder`].
27#[derive(bon::Builder)]
28#[builder(finish_fn(vis = "", name = build_internal))]
29#[non_exhaustive]
30pub struct RuntimeOptions {
31    /// Telemetry configuration options.
32    #[builder(default)]
33    telemetry_options: TelemetryOptions,
34    /// Optional worker heartbeat interval for all workers created with this runtime.
35    ///
36    /// The interval must be between 1 and 60 seconds, inclusive.
37    #[builder(required, default = Some(Duration::from_secs(60)))]
38    heartbeat_interval: Option<Duration>,
39    /// Disable including runtime, hosting, and platform information in worker heartbeats.
40    #[builder(default)]
41    disable_environment_info: bool,
42}
43
44impl Default for RuntimeOptions {
45    fn default() -> Self {
46        Self::builder().build().expect("builder defaults are valid")
47    }
48}
49
50impl<S: runtime_options_builder::State> RuntimeOptionsBuilder<S> {
51    /// Builds the runtime options.
52    ///
53    /// # Errors
54    /// Returns an error if `heartbeat_interval` is set but is not between 1 and 60 seconds,
55    /// inclusive.
56    pub fn build(self) -> Result<RuntimeOptions, String> {
57        let options = self.build_internal();
58        if let Some(interval) = options.heartbeat_interval
59            && (interval < Duration::from_secs(1) || interval > Duration::from_secs(60))
60        {
61            return Err(format!(
62                "heartbeat_interval ({interval:?}) must be between 1s and 60s",
63            ));
64        }
65        Ok(options)
66    }
67}
68
69impl From<RuntimeOptions> for CoreRuntimeOptions {
70    fn from(options: RuntimeOptions) -> Self {
71        CoreRuntimeOptions::builder()
72            .telemetry_options(options.telemetry_options)
73            .heartbeat_interval(options.heartbeat_interval)
74            .disable_environment_info(options.disable_environment_info)
75            .build()
76            .expect("SDK runtime options have already been validated")
77    }
78}
79
80/// Holds shared state and components used by Rust SDK workers.
81pub struct Runtime(CoreRuntime);
82
83impl Runtime {
84    /// Creates a runtime with a newly constructed Tokio runtime.
85    pub fn new<F>(
86        options: RuntimeOptions,
87        tokio_builder: TokioRuntimeBuilder<F>,
88    ) -> Result<Self, anyhow::Error>
89    where
90        F: Fn() + Send + Sync + 'static,
91    {
92        CoreRuntime::new(options.into(), tokio_builder).map(Self)
93    }
94
95    /// Creates a runtime using the currently active Tokio runtime.
96    ///
97    /// # Panics
98    /// Panics if there is no currently active Tokio runtime.
99    pub fn new_assume_tokio(options: RuntimeOptions) -> Result<Self, anyhow::Error> {
100        CoreRuntime::new_assume_tokio(options.into()).map(Self)
101    }
102
103    /// Creates a runtime from an initialized telemetry instance using the currently active Tokio
104    /// runtime.
105    ///
106    /// # Panics
107    /// Panics if there is no currently active Tokio runtime.
108    pub fn new_assume_tokio_initialized_telem(
109        telemetry: TelemetryInstance,
110        heartbeat_interval: Option<Duration>,
111    ) -> Self {
112        Self(CoreRuntime::new_assume_tokio_initialized_telem(
113            telemetry,
114            heartbeat_interval,
115        ))
116    }
117}
118
119impl Deref for Runtime {
120    type Target = CoreRuntime;
121
122    fn deref(&self) -> &Self::Target {
123        &self.0
124    }
125}
126
127impl DerefMut for Runtime {
128    fn deref_mut(&mut self) -> &mut Self::Target {
129        &mut self.0
130    }
131}