Skip to main content

temporalio_client/
options_structs.rs

1use crate::{HttpConnectProxyOptions, RetryOptions, VERSION, callback_based};
2use http::Uri;
3use std::{collections::HashMap, time::Duration};
4use temporalio_common::{
5    data_converters::DataConverter,
6    protos::temporal::api::{
7        common::{
8            self,
9            v1::{Header, Payload, Payloads},
10        },
11        enums::v1::{
12            ArchivalState, HistoryEventFilterType, QueryRejectCondition, WorkflowIdConflictPolicy,
13            WorkflowIdReusePolicy,
14        },
15        replication::v1::ClusterReplicationConfig,
16        workflowservice::v1::RegisterNamespaceRequest,
17    },
18    telemetry::metrics::TemporalMeter,
19};
20use url::Url;
21
22/// Options for [crate::Connection::connect].
23#[derive(bon::Builder, Clone, Debug)]
24#[non_exhaustive]
25#[builder(start_fn = new, on(String, into), state_mod(vis = "pub"))]
26pub struct ConnectionOptions {
27    /// The server to connect to.
28    #[builder(start_fn, into)]
29    pub target: Url,
30    /// A human-readable string that can identify this process. Defaults to empty string.
31    #[builder(default)]
32    pub identity: String,
33    /// When set, this client will record metrics using the provided meter. The meter can be
34    /// obtained from [temporalio_common::telemetry::TelemetryInstance::get_temporal_metric_meter].
35    pub metrics_meter: Option<TemporalMeter>,
36    /// If specified, use TLS as configured by the [TlsOptions] struct. If this is set core will
37    /// attempt to use TLS when connecting to the Temporal server. Lang SDK is expected to pass any
38    /// certs or keys as bytes, loading them from disk itself if needed.
39    pub tls_options: Option<TlsOptions>,
40    /// If set, override the origin used when connecting. May be useful in rare situations where tls
41    /// verification needs to use a different name from what should be set as the `:authority`
42    /// header. If [TlsOptions::domain] is set, and this is not, this will be set to
43    /// `https://<domain>`, effectively making the `:authority` header consistent with the domain
44    /// override.
45    pub override_origin: Option<Uri>,
46    /// An API key to use for auth. If set, TLS will be enabled by default, but without any mTLS
47    /// specific settings.
48    pub api_key: Option<String>,
49    /// Retry configuration for the server client. Default is [RetryOptions::default]
50    #[builder(default)]
51    pub retry_options: RetryOptions,
52    /// If set, HTTP2 gRPC keep alive will be enabled.
53    /// To enable with default settings, use `.keep_alive(Some(ClientKeepAliveConfig::default()))`.
54    #[builder(required, default = Some(ClientKeepAliveOptions::default()))]
55    pub keep_alive: Option<ClientKeepAliveOptions>,
56    /// HTTP headers to include on every RPC call.
57    ///
58    /// These must be valid gRPC metadata keys, and must not be binary metadata keys (ending in
59    /// `-bin). To set binary headers, use [ConnectionOptions::binary_headers]. Invalid header keys
60    /// or values will cause an error to be returned when connecting.
61    pub headers: Option<HashMap<String, String>>,
62    /// HTTP headers to include on every RPC call as binary gRPC metadata (encoded as base64).
63    ///
64    /// These must be valid binary gRPC metadata keys (and end with a `-bin` suffix). Invalid
65    /// header keys will cause an error to be returned when connecting.
66    pub binary_headers: Option<HashMap<String, Vec<u8>>>,
67    /// HTTP CONNECT proxy to use for this client.
68    pub http_connect_proxy: Option<HttpConnectProxyOptions>,
69    /// If set, DNS-based load balancing is enabled. When the target is a hostname (not an IP
70    /// literal), DNS is resolved to all addresses and requests are distributed across them.
71    /// Incompatible with `service_override` and `http_connect_proxy`. Setting either in addition
72    /// to this field is an error. Set to `None` to disable.
73    #[builder(required, default = Some(DnsLoadBalancingOptions::default()))]
74    pub dns_load_balancing: Option<DnsLoadBalancingOptions>,
75    /// If set true, error code labels will not be included on request failure metrics.
76    #[builder(default)]
77    pub disable_error_code_metric_tags: bool,
78    /// If set, all gRPC calls will be routed through the provided service.
79    pub service_override: Option<callback_based::CallbackBasedGrpcService>,
80
81    // Internal / Core-based SDK only options below =============================================
82    /// If set true, get_system_info will not be called upon connection.
83    #[builder(default)]
84    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
85    pub(crate) skip_get_system_info: bool,
86    /// The name of the SDK being implemented on top of core. Is set as `client-name` header in
87    /// all RPC calls
88    #[builder(default = "temporal-rust".to_owned())]
89    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
90    pub(crate) client_name: String,
91    // TODO [rust-sdk-branch]: SDK should set this to its version. Doing that probably easiest
92    // after adding proper client interceptors.
93    /// The version of the SDK being implemented on top of core. Is set as `client-version` header
94    /// in all RPC calls. The server decides if the client is supported based on this.
95    #[builder(default = VERSION.to_owned())]
96    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
97    pub(crate) client_version: String,
98}
99
100// Setters/getters for fields that should only be touched by SDK implementers.
101#[cfg(feature = "core-based-sdk")]
102impl ConnectionOptions {
103    /// Set whether or not get_system_info will be called upon connection.
104    pub fn set_skip_get_system_info(&mut self, skip: bool) {
105        self.skip_get_system_info = skip;
106    }
107    /// Get whether or not get_system_info will be called upon connection.
108    pub fn get_skip_get_system_info(&self) -> bool {
109        self.skip_get_system_info
110    }
111    /// Get the name of the SDK being implemented on top of core.
112    pub fn get_client_name(&self) -> &str {
113        &self.client_name
114    }
115    /// Get the version of the SDK being implemented on top of core.
116    pub fn get_client_version(&self) -> &str {
117        &self.client_version
118    }
119}
120
121/// Options for [crate::Client::new].
122#[derive(Clone, Debug, bon::Builder)]
123#[non_exhaustive]
124#[builder(start_fn = new, on(String, into), state_mod(vis = "pub"))]
125pub struct ClientOptions {
126    /// The namespace this client will be bound to.
127    #[builder(start_fn)]
128    pub namespace: String,
129    /// The data converter used for serializing/deserializing payloads.
130    #[builder(default)]
131    pub data_converter: DataConverter,
132}
133
134/// Configuration options for TLS
135#[derive(Clone, Debug, Default)]
136pub struct TlsOptions {
137    /// Bytes representing the root CA certificate used by the server. If not set, and the server's
138    /// cert is issued by someone the operating system trusts, verification will still work (ex:
139    /// Cloud offering).
140    pub server_root_ca_cert: Option<Vec<u8>>,
141    /// Sets the domain name against which to verify the server's TLS certificate. If not provided,
142    /// the domain name will be extracted from the URL used to connect.
143    pub domain: Option<String>,
144    /// TLS info for the client. If specified, core will attempt to use mTLS.
145    pub client_tls_options: Option<ClientTlsOptions>,
146}
147
148/// If using mTLS, both the client cert and private key must be specified, this contains them.
149#[derive(Clone)]
150pub struct ClientTlsOptions {
151    /// The certificate for this client, encoded as PEM
152    pub client_cert: Vec<u8>,
153    /// The private key for this client, encoded as PEM
154    pub client_private_key: Vec<u8>,
155}
156
157/// Client keep alive configuration.
158#[derive(Clone, Debug)]
159pub struct ClientKeepAliveOptions {
160    /// Interval to send HTTP2 keep alive pings.
161    pub interval: Duration,
162    /// Timeout that the keep alive must be responded to within or the connection will be closed.
163    pub timeout: Duration,
164}
165
166impl Default for ClientKeepAliveOptions {
167    fn default() -> Self {
168        Self {
169            interval: Duration::from_secs(30),
170            timeout: Duration::from_secs(15),
171        }
172    }
173}
174
175/// Options for DNS-based load balancing.
176#[derive(Clone, Debug)]
177#[non_exhaustive]
178pub struct DnsLoadBalancingOptions {
179    /// How often to re-resolve DNS. Defaults to 30 seconds.
180    pub resolution_interval: Duration,
181}
182
183impl Default for DnsLoadBalancingOptions {
184    fn default() -> Self {
185        Self {
186            resolution_interval: Duration::from_secs(30),
187        }
188    }
189}
190
191impl std::fmt::Debug for ClientTlsOptions {
192    // Intentionally omit details here since they could leak a key if ever printed
193    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194        write!(f, "ClientTlsOptions(..)")
195    }
196}
197
198/// Options for starting a workflow execution.
199#[derive(Debug, Clone, bon::Builder)]
200#[builder(start_fn = new, on(String, into))]
201#[non_exhaustive]
202pub struct WorkflowStartOptions {
203    /// The task queue to run the workflow on.
204    #[builder(start_fn)]
205    pub task_queue: String,
206
207    /// The workflow ID.
208    #[builder(start_fn)]
209    pub workflow_id: String,
210
211    /// Set the policy for reusing the workflow id
212    #[builder(default)]
213    pub id_reuse_policy: WorkflowIdReusePolicy,
214
215    /// Set the policy for how to resolve conflicts with running policies.
216    /// NOTE: This is ignored for child workflows.
217    #[builder(default)]
218    pub id_conflict_policy: WorkflowIdConflictPolicy,
219
220    /// Optionally set the execution timeout for the workflow
221    /// <https://docs.temporal.io/workflows/#workflow-execution-timeout>
222    pub execution_timeout: Option<Duration>,
223
224    /// Optionally indicates the default run timeout for a workflow run
225    pub run_timeout: Option<Duration>,
226
227    /// Optionally indicates the default task timeout for a workflow run
228    pub task_timeout: Option<Duration>,
229
230    /// Optionally set a cron schedule for the workflow
231    pub cron_schedule: Option<String>,
232
233    /// Optionally associate extra search attributes with a workflow
234    pub search_attributes: Option<HashMap<String, Payload>>,
235
236    /// Optionally enable Eager Workflow Start, a latency optimization using local workers
237    /// NOTE: Experimental
238    #[builder(default)]
239    pub enable_eager_workflow_start: bool,
240
241    /// Optionally set a retry policy for the workflow
242    pub retry_policy: Option<common::v1::RetryPolicy>,
243
244    /// If set, send a signal to the workflow atomically with start.
245    /// The workflow will receive this signal before its first task.
246    pub start_signal: Option<WorkflowStartSignal>,
247
248    /// Links to associate with the workflow. Ex: References to a nexus operation.
249    #[builder(default)]
250    pub links: Vec<common::v1::Link>,
251
252    /// Callbacks that will be invoked upon workflow completion. For, ex, completing nexus
253    /// operations.
254    #[builder(default)]
255    pub completion_callbacks: Vec<common::v1::Callback>,
256
257    /// Priority for the workflow. Defaults to all-inherited (empty).
258    #[builder(default)]
259    pub priority: Priority,
260
261    /// Headers to include with the start request.
262    pub header: Option<Header>,
263
264    /// Single-line static summary for the workflow, shown in the Temporal UI.
265    pub static_summary: Option<String>,
266
267    /// Multi-line static details for the workflow, shown in the Temporal UI.
268    pub static_details: Option<String>,
269}
270
271/// A signal to send atomically when starting a workflow.
272/// Use with `WorkflowStartOptions::start_signal` to achieve signal-with-start behavior.
273#[derive(Debug, Clone, bon::Builder)]
274#[builder(start_fn = new, on(String, into))]
275#[non_exhaustive]
276pub struct WorkflowStartSignal {
277    /// Name of the signal to send.
278    #[builder(start_fn)]
279    pub signal_name: String,
280    /// Payload for the signal.
281    pub input: Option<Payloads>,
282    /// Headers for the signal.
283    pub header: Option<Header>,
284}
285
286pub use temporalio_common::Priority;
287
288/// Options for fetching workflow results
289#[derive(Debug, Clone, Copy, bon::Builder)]
290#[non_exhaustive]
291pub struct WorkflowGetResultOptions {
292    /// If true (the default), follows to the next workflow run in the execution chain while
293    /// retrieving results.
294    #[builder(default = true)]
295    pub follow_runs: bool,
296}
297impl Default for WorkflowGetResultOptions {
298    fn default() -> Self {
299        Self { follow_runs: true }
300    }
301}
302
303/// Options for starting a workflow update.
304#[derive(Debug, Clone, Default, bon::Builder)]
305#[non_exhaustive]
306pub struct WorkflowExecuteUpdateOptions {
307    /// Update ID for idempotency.
308    pub update_id: Option<String>,
309    /// Headers to include.
310    pub header: Option<Header>,
311}
312
313/// Options for sending a signal to a workflow.
314#[derive(Debug, Clone, Default, bon::Builder)]
315#[non_exhaustive]
316pub struct WorkflowSignalOptions {
317    /// Request ID for idempotency. If not provided, a UUID will be generated.
318    pub request_id: Option<String>,
319    /// Headers to include with the signal.
320    pub header: Option<Header>,
321}
322
323/// Options for querying a workflow.
324#[derive(Debug, Clone, Default, bon::Builder)]
325#[non_exhaustive]
326pub struct WorkflowQueryOptions {
327    /// Query reject condition. Determines when the query should be rejected
328    /// based on workflow state.
329    pub reject_condition: Option<QueryRejectCondition>,
330    /// Headers to include with the query.
331    pub header: Option<Header>,
332}
333
334/// Options for cancelling a workflow.
335#[derive(Debug, Clone, Default, bon::Builder)]
336#[builder(on(String, into))]
337#[non_exhaustive]
338pub struct WorkflowCancelOptions {
339    /// Reason for cancellation.
340    #[builder(default)]
341    pub reason: String,
342    /// Request ID for idempotency. If not provided, a UUID will be generated.
343    pub request_id: Option<String>,
344}
345
346/// Options for terminating a workflow.
347#[derive(Debug, Clone, Default, bon::Builder)]
348#[builder(on(String, into))]
349#[non_exhaustive]
350pub struct WorkflowTerminateOptions {
351    /// Reason for termination.
352    #[builder(default)]
353    pub reason: String,
354    /// Additional details to include with the termination.
355    pub details: Option<Payloads>,
356}
357
358/// Options for describing a workflow.
359#[derive(Debug, Clone, Default, bon::Builder)]
360#[non_exhaustive]
361pub struct WorkflowDescribeOptions {}
362
363/// Default workflow execution retention for a Namespace is 3 days
364const DEFAULT_WORKFLOW_EXECUTION_RETENTION_PERIOD: Duration = Duration::from_secs(60 * 60 * 24 * 3);
365
366/// Helper struct for `register_namespace`.
367#[derive(Clone, Debug, bon::Builder)]
368#[builder(on(String, into))]
369pub struct RegisterNamespaceOptions {
370    /// Name (required)
371    pub namespace: String,
372    /// Description (required)
373    pub description: String,
374    /// Owner's email
375    #[builder(default)]
376    pub owner_email: String,
377    /// Workflow execution retention period
378    #[builder(default = DEFAULT_WORKFLOW_EXECUTION_RETENTION_PERIOD)]
379    pub workflow_execution_retention_period: Duration,
380    /// Cluster settings
381    #[builder(default)]
382    pub clusters: Vec<ClusterReplicationConfig>,
383    /// Active cluster name
384    #[builder(default)]
385    pub active_cluster_name: String,
386    /// Custom Data
387    #[builder(default)]
388    pub data: HashMap<String, String>,
389    /// Security Token
390    #[builder(default)]
391    pub security_token: String,
392    /// Global namespace
393    #[builder(default)]
394    pub is_global_namespace: bool,
395    /// History Archival setting
396    #[builder(default = ArchivalState::Unspecified)]
397    pub history_archival_state: ArchivalState,
398    /// History Archival uri
399    #[builder(default)]
400    pub history_archival_uri: String,
401    /// Visibility Archival setting
402    #[builder(default = ArchivalState::Unspecified)]
403    pub visibility_archival_state: ArchivalState,
404    /// Visibility Archival uri
405    #[builder(default)]
406    pub visibility_archival_uri: String,
407}
408
409impl From<RegisterNamespaceOptions> for RegisterNamespaceRequest {
410    fn from(val: RegisterNamespaceOptions) -> Self {
411        RegisterNamespaceRequest {
412            namespace: val.namespace,
413            description: val.description,
414            owner_email: val.owner_email,
415            workflow_execution_retention_period: val
416                .workflow_execution_retention_period
417                .try_into()
418                .ok(),
419            clusters: val.clusters,
420            active_cluster_name: val.active_cluster_name,
421            data: val.data,
422            security_token: val.security_token,
423            is_global_namespace: val.is_global_namespace,
424            history_archival_state: val.history_archival_state as i32,
425            history_archival_uri: val.history_archival_uri,
426            visibility_archival_state: val.visibility_archival_state as i32,
427            visibility_archival_uri: val.visibility_archival_uri,
428        }
429    }
430}
431
432/// Options for fetching workflow history.
433#[derive(Debug, Clone, Default, bon::Builder)]
434#[non_exhaustive]
435pub struct WorkflowFetchHistoryOptions {
436    /// Whether to skip archival.
437    #[builder(default)]
438    pub skip_archival: bool,
439    /// If set true, the fetch will wait for a new event before returning.
440    #[builder(default)]
441    pub wait_new_event: bool,
442    /// Specifies which kind of events will be retrieved. Defaults to all events.
443    #[builder(default = HistoryEventFilterType::AllEvent)]
444    pub event_filter_type: HistoryEventFilterType,
445}
446
447/// Which lifecycle stage to wait for when starting an update.
448#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
449pub enum WorkflowUpdateWaitStage {
450    /// This stage is reached when the server receives the update to process.
451    /// This is currently an invalid value on start.
452    Admitted,
453    /// Wait until the update is accepted by the workflow (validator passed).
454    #[default]
455    Accepted,
456    /// Wait until the update has completed.
457    Completed,
458}
459
460/// Options for starting an update without waiting for completion.
461#[derive(Debug, Clone, Default, bon::Builder)]
462#[non_exhaustive]
463pub struct WorkflowStartUpdateOptions {
464    /// Update ID for idempotency. If not provided, a UUID will be generated.
465    pub update_id: Option<String>,
466    /// Headers to include with the update.
467    pub header: Option<Header>,
468    /// The lifecycle stage to wait for before returning the handle.
469    #[builder(default)]
470    pub wait_for_stage: WorkflowUpdateWaitStage,
471}
472
473/// Options for listing workflows.
474#[derive(Debug, Clone, Default, bon::Builder)]
475#[non_exhaustive]
476pub struct WorkflowListOptions {
477    /// Maximum number of workflows to return.
478    /// If not specified, returns all matching workflows.
479    pub limit: Option<usize>,
480}
481
482/// Options for counting workflows.
483#[derive(Debug, Clone, Default, bon::Builder)]
484#[non_exhaustive]
485pub struct WorkflowCountOptions {}