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 {}