Skip to main content

temporalio_client/
options_structs.rs

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