Skip to main content

temporalio_client/
options_structs.rs

1use crate::{
2    ClientInterceptor, ClientPlugin, ErasedClientPlugin, HttpConnectProxyOptions, RetryOptions,
3    RpcOptions, VERSION, callback_based,
4};
5use http::Uri;
6use std::{collections::HashMap, sync::Arc, time::Duration};
7use temporalio_common::{
8    ActivityCloseTimeouts, RetryPolicy,
9    data_converters::DataConverter,
10    protos::temporal::api::{
11        common::{
12            self,
13            v1::{Header, Payloads},
14        },
15        enums::v1::{
16            ActivityIdConflictPolicy as ProtoActivityIdConflictPolicy,
17            ActivityIdReusePolicy as ProtoActivityIdReusePolicy, ArchivalState,
18            HistoryEventFilterType, QueryRejectCondition, WorkflowIdConflictPolicy,
19            WorkflowIdReusePolicy,
20        },
21        replication::v1::ClusterReplicationConfig,
22        workflowservice::v1::RegisterNamespaceRequest,
23    },
24    search_attributes::SearchAttributes,
25    telemetry::metrics::TemporalMeter,
26};
27#[cfg(feature = "dynamic-tls")]
28use tokio_rustls::rustls::client::ResolvesClientCert;
29use tokio_rustls::rustls::client::danger::ServerCertVerifier;
30use url::Url;
31
32/// Options for [crate::Connection::connect].
33#[derive(bon::Builder, Clone, Debug)]
34#[non_exhaustive]
35#[builder(start_fn = new, on(String, into), state_mod(vis = "pub"))]
36pub struct ConnectionOptions {
37    /// The server to connect to.
38    #[builder(start_fn, into)]
39    pub target: Url,
40    /// A human-readable string that can identify this process. Defaults to empty string.
41    #[builder(default)]
42    pub identity: String,
43    /// When set, this client will record metrics using the provided meter. The meter can be
44    /// obtained from [temporalio_common::telemetry::TelemetryInstance::get_temporal_metric_meter].
45    pub metrics_meter: Option<TemporalMeter>,
46    /// If specified, use TLS as configured by the [TlsOptions] struct. If this is set core will
47    /// attempt to use TLS when connecting to the Temporal server. Lang SDK is expected to pass any
48    /// certs or keys as bytes, loading them from disk itself if needed.
49    pub tls_options: Option<TlsOptions>,
50    /// If set, override the origin used when connecting. May be useful in rare situations where tls
51    /// verification needs to use a different name from what should be set as the `:authority`
52    /// header. If [TlsOptions::domain] is set, and this is not, this will be set to
53    /// `https://<domain>`, effectively making the `:authority` header consistent with the domain
54    /// override.
55    pub override_origin: Option<Uri>,
56    /// An API key to use for auth. If set, TLS will be enabled by default, but without any mTLS
57    /// specific settings.
58    pub api_key: Option<String>,
59    /// When set, limits the time allowed to establish the initial TCP/TLS connection to the
60    /// server. If the connection cannot be established within this duration, `connect` will
61    /// return an error. When `None` (the default), no explicit timeout is applied and the
62    /// connection attempt may block indefinitely (subject to OS-level TCP timeouts).
63    pub connect_timeout: Option<Duration>,
64    /// Retry configuration for the server client. Default is [RetryOptions::default]
65    #[builder(default)]
66    pub retry_options: RetryOptions,
67    /// If set, HTTP2 gRPC keep alive will be enabled.
68    /// To enable with default settings, use `.keep_alive(Some(ClientKeepAliveConfig::default()))`.
69    #[builder(required, default = Some(ClientKeepAliveOptions::default()))]
70    pub keep_alive: Option<ClientKeepAliveOptions>,
71    /// HTTP headers to include on every RPC call.
72    ///
73    /// These must be valid gRPC metadata keys, and must not be binary metadata keys (ending in
74    /// `-bin). To set binary headers, use [ConnectionOptions::binary_headers]. Invalid header keys
75    /// or values will cause an error to be returned when connecting.
76    pub headers: Option<HashMap<String, String>>,
77    /// HTTP headers to include on every RPC call as binary gRPC metadata (encoded as base64).
78    ///
79    /// These must be valid binary gRPC metadata keys (and end with a `-bin` suffix). Invalid
80    /// header keys will cause an error to be returned when connecting.
81    pub binary_headers: Option<HashMap<String, Vec<u8>>>,
82    /// HTTP CONNECT proxy to use for this client.
83    pub http_connect_proxy: Option<HttpConnectProxyOptions>,
84    /// If set, DNS-based load balancing is enabled. When the target is a hostname (not an IP
85    /// literal), DNS is resolved to all addresses and requests are distributed across them.
86    /// Incompatible with `service_override` and `http_connect_proxy`. Setting either in addition
87    /// to this field is an error. Set to `None` to disable.
88    #[builder(required, default = Some(DnsLoadBalancingOptions::default()))]
89    pub dns_load_balancing: Option<DnsLoadBalancingOptions>,
90    /// If set true, error code labels will not be included on request failure metrics.
91    #[builder(default)]
92    pub disable_error_code_metric_tags: bool,
93    /// If set, all gRPC calls will be routed through the provided service.
94    pub service_override: Option<callback_based::CallbackBasedGrpcService>,
95    /// Controls transport-level gRPC compression for the client. Defaults to
96    /// [GrpcCompression::Gzip], which compresses outbound request bodies and accepts
97    /// compressed responses. Set to [GrpcCompression::None] to opt out.
98    /// If service_override is specified, is forced to `None`.
99    #[builder(default)]
100    pub grpc_compression: GrpcCompression,
101    /// Payload size limit options for this connection. Defaults to the standard warning thresholds;
102    /// disable an individual warning by setting its threshold to `0`.
103    /// NOTE: Experimental
104    #[builder(default)]
105    pub payload_limits: PayloadLimitsOptions,
106
107    // Internal / Core-based SDK only options below =============================================
108    /// If set true, get_system_info will not be called upon connection.
109    #[builder(default)]
110    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
111    pub(crate) skip_get_system_info: bool,
112    /// The name of the SDK being implemented on top of core. Is set as `client-name` header in
113    /// all RPC calls
114    #[builder(default = "temporal-rust".to_owned())]
115    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
116    pub(crate) client_name: String,
117    // TODO [rust-sdk-branch]: SDK should set this to its version. Doing that probably easiest
118    // after adding proper client interceptors.
119    /// The version of the SDK being implemented on top of core. Is set as `client-version` header
120    /// in all RPC calls. The server decides if the client is supported based on this.
121    #[builder(default = VERSION.to_owned())]
122    #[cfg_attr(feature = "core-based-sdk", builder(setters(vis = "pub")))]
123    pub(crate) client_version: String,
124}
125
126// Setters/getters for fields that should only be touched by SDK implementers.
127#[cfg(feature = "core-based-sdk")]
128impl ConnectionOptions {
129    /// Set whether or not get_system_info will be called upon connection.
130    pub fn set_skip_get_system_info(&mut self, skip: bool) {
131        self.skip_get_system_info = skip;
132    }
133    /// Get whether or not get_system_info will be called upon connection.
134    pub fn get_skip_get_system_info(&self) -> bool {
135        self.skip_get_system_info
136    }
137    /// Get the name of the SDK being implemented on top of core.
138    pub fn get_client_name(&self) -> &str {
139        &self.client_name
140    }
141    /// Get the version of the SDK being implemented on top of core.
142    pub fn get_client_version(&self) -> &str {
143        &self.client_version
144    }
145}
146
147/// Options for [crate::Client::new].
148#[derive(Clone, derive_more::Debug, bon::Builder)]
149#[non_exhaustive]
150#[builder(start_fn = new, on(String, into), state_mod(vis = "pub"))]
151pub struct ClientOptions {
152    /// The namespace this client will be bound to.
153    #[builder(start_fn)]
154    pub namespace: String,
155
156    #[builder(field)]
157    #[debug(skip)]
158    plugins: Vec<ErasedClientPlugin>,
159
160    #[builder(field)]
161    #[debug(skip)]
162    client_plugins_applied: bool,
163
164    /// The data converter used for serializing/deserializing payloads.
165    #[builder(default)]
166    pub data_converter: DataConverter,
167    /// Interceptors for high-level client operations, ordered outermost to innermost.
168    #[builder(default)]
169    #[debug(skip)]
170    pub client_interceptors: Vec<Arc<dyn ClientInterceptor>>,
171}
172
173impl<S: client_options_builder::State> ClientOptionsBuilder<S> {
174    /// Register a type-erased client plugin.
175    ///
176    /// **Experimental:** This API may change or be removed.
177    pub fn plugin<P: Into<ErasedClientPlugin>>(mut self, plugin: P) -> Self {
178        self.plugins.push(plugin.into());
179        self
180    }
181
182    /// Register type-erased client plugins in iteration order.
183    ///
184    /// **Experimental:** This API may change or be removed.
185    pub fn plugins<I, P>(mut self, plugins: I) -> Self
186    where
187        I: IntoIterator<Item = P>,
188        P: Into<ErasedClientPlugin>,
189    {
190        self.plugins.extend(plugins.into_iter().map(Into::into));
191        self
192    }
193
194    /// Register a client-only plugin.
195    ///
196    /// **Experimental:** This API may change or be removed.
197    pub fn client_plugin<P: ClientPlugin>(mut self, plugin: P) -> Self {
198        self.plugins.push(ErasedClientPlugin::new(plugin));
199        self
200    }
201}
202
203impl ClientOptions {
204    /// Return the registered plugins.
205    ///
206    /// This is intended for SDK integrations that propagate worker plugin registrations.
207    ///
208    /// **Experimental:** This API may change or be removed.
209    pub fn plugins(&self) -> &[ErasedClientPlugin] {
210        &self.plugins
211    }
212
213    pub(crate) fn client_plugins_applied(&self) -> bool {
214        self.client_plugins_applied
215    }
216
217    pub(crate) fn mark_client_plugins_applied(&mut self) {
218        self.client_plugins_applied = true;
219    }
220}
221
222/// Selects the transport-level compression used for gRPC calls. See
223/// [ConnectionOptions::grpc_compression].
224#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
225#[non_exhaustive]
226pub enum GrpcCompression {
227    /// Do not compress requests or advertise acceptance of compressed responses.
228    None,
229    /// Gzip-compress outbound requests and accept gzip-compressed responses.
230    #[default]
231    Gzip,
232}
233
234/// Configuration options for TLS
235#[derive(Clone, bon::Builder)]
236#[non_exhaustive]
237pub struct TlsOptions {
238    /// Bytes representing the root CA certificate used by the server. If not set, and the server's
239    /// cert is issued by someone the operating system trusts, verification will still work (ex:
240    /// Cloud offering).
241    pub server_root_ca_cert: Option<Vec<u8>>,
242    /// Sets the domain name against which to verify the server's TLS certificate. If not provided,
243    /// the domain name will be extracted from the URL used to connect.
244    pub domain: Option<String>,
245    /// TLS info for the client. If specified, core will attempt to use mTLS.
246    ///
247    /// Mutually exclusive with [`client_cert_resolver`](TlsOptions::client_cert_resolver).
248    /// Setting both is an error.
249    pub client_tls_options: Option<ClientTlsOptions>,
250    /// Optional custom server certificate verifier. When set, this replaces the default
251    /// certificate verification and `server_root_ca_cert` is ignored.
252    ///
253    /// This is useful for:
254    /// - Certificate pinning
255    /// - Custom trust-domain validation (e.g., SAN-URI extraction)
256    /// - Federated root certificate stores
257    ///
258    /// # WARNING
259    /// Implementing a custom `ServerCertVerifier` can lead to severely insecure TLS connections
260    /// (e.g., disabling all validation or allowing man-in-the-middle attacks) if not done carefully.
261    /// Only use this if you know exactly what you are doing.
262    ///
263    /// The verifier must implement [`ServerCertVerifier`] from the `rustls` crate.
264    /// Note that `domain` is still respected for the `:authority` header / origin override
265    /// even when a custom verifier is set.
266    pub server_cert_verifier: Option<Arc<dyn ServerCertVerifier>>,
267    /// Optional dynamic client certificate resolver for transparent mTLS certificate rotation.
268    ///
269    /// Mutually exclusive with [`client_tls_options`](TlsOptions::client_tls_options).
270    /// Setting both is an error.
271    #[cfg(feature = "dynamic-tls")]
272    pub client_cert_resolver: Option<Arc<dyn ResolvesClientCert>>,
273}
274
275impl Default for TlsOptions {
276    fn default() -> Self {
277        Self::builder().build()
278    }
279}
280
281impl std::fmt::Debug for TlsOptions {
282    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283        let mut s = f.debug_struct("TlsOptions");
284        s.field(
285            "server_root_ca_cert",
286            &self
287                .server_root_ca_cert
288                .as_ref()
289                .map(|c| format!("{} bytes", c.len())),
290        );
291        s.field("domain", &self.domain);
292        s.field("client_tls_options", &self.client_tls_options);
293        s.field(
294            "server_cert_verifier",
295            &self.server_cert_verifier.as_ref().map(|_| "<custom>"),
296        );
297        #[cfg(feature = "dynamic-tls")]
298        s.field(
299            "client_cert_resolver",
300            &self.client_cert_resolver.as_ref().map(|_| "<custom>"),
301        );
302        s.finish()
303    }
304}
305
306/// If using mTLS, both the client cert and private key must be specified, this contains them.
307#[derive(Clone, bon::Builder)]
308#[non_exhaustive]
309pub struct ClientTlsOptions {
310    /// The certificate for this client, encoded as PEM
311    pub client_cert: Vec<u8>,
312    /// The private key for this client, encoded as PEM
313    pub client_private_key: Vec<u8>,
314}
315
316/// Client keep alive configuration.
317#[derive(Clone, Debug, PartialEq, bon::Builder)]
318#[non_exhaustive]
319pub struct ClientKeepAliveOptions {
320    /// Interval to send HTTP2 keep alive pings.
321    #[builder(default = Duration::from_secs(30))]
322    pub interval: Duration,
323    /// Timeout that the keep alive must be responded to within or the connection will be closed.
324    #[builder(default = Duration::from_secs(15))]
325    pub timeout: Duration,
326}
327
328impl Default for ClientKeepAliveOptions {
329    fn default() -> Self {
330        Self::builder().build()
331    }
332}
333
334/// Options for DNS-based load balancing.
335#[derive(Clone, Debug, PartialEq, bon::Builder)]
336#[non_exhaustive]
337pub struct DnsLoadBalancingOptions {
338    /// How often to re-resolve DNS. Defaults to 30 seconds.
339    #[builder(default = Duration::from_secs(30))]
340    pub resolution_interval: Duration,
341}
342
343impl Default for DnsLoadBalancingOptions {
344    fn default() -> Self {
345        Self::builder().build()
346    }
347}
348
349/// Payload size limit options for a connection.
350/// NOTE: Experimental
351#[derive(Clone, Debug, PartialEq, bon::Builder)]
352#[non_exhaustive]
353pub struct PayloadLimitsOptions {
354    /// Warning threshold (bytes) for the size of an outbound payload-bearing field; over-threshold
355    /// fields are logged but still sent to server. Defaults to 512 KiB. Set to `0` to disable.
356    #[builder(default = 512 * 1024)]
357    pub payloads_warn_size: u64,
358    /// Warning threshold (bytes) for outbound memo sizes; over-threshold memos are logged but still
359    /// sent to server. Defaults to 2 KiB. Set to `0` to disable.
360    #[builder(default = 2 * 1024)]
361    pub memo_warn_size: u64,
362}
363
364impl Default for PayloadLimitsOptions {
365    fn default() -> Self {
366        Self::builder().build()
367    }
368}
369
370impl std::fmt::Debug for ClientTlsOptions {
371    // Intentionally omit details here since they could leak a key if ever printed
372    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
373        write!(f, "ClientTlsOptions(..)")
374    }
375}
376
377/// Options for starting a workflow execution.
378#[derive(Debug, Clone, bon::Builder)]
379#[builder(start_fn = new, on(String, into))]
380#[non_exhaustive]
381pub struct WorkflowStartOptions {
382    /// The task queue to run the workflow on.
383    #[builder(start_fn)]
384    pub task_queue: String,
385
386    /// The workflow ID.
387    #[builder(start_fn)]
388    pub workflow_id: String,
389
390    /// Set the policy for reusing the workflow id
391    #[builder(default)]
392    pub id_reuse_policy: WorkflowIdReusePolicy,
393
394    /// Set the policy for how to resolve conflicts with running policies.
395    /// NOTE: This is ignored for child workflows.
396    #[builder(default)]
397    pub id_conflict_policy: WorkflowIdConflictPolicy,
398
399    /// Optionally set the execution timeout for the workflow
400    /// <https://docs.temporal.io/workflows/#workflow-execution-timeout>
401    pub execution_timeout: Option<Duration>,
402
403    /// Optionally indicates the default run timeout for a workflow run
404    pub run_timeout: Option<Duration>,
405
406    /// Optionally indicates the default task timeout for a workflow run
407    pub task_timeout: Option<Duration>,
408
409    /// Optionally set a cron schedule for the workflow
410    pub cron_schedule: Option<String>,
411
412    /// Additional search attributes for the workflow.
413    pub search_attributes: Option<SearchAttributes>,
414
415    /// Optionally enable Eager Workflow Start, a latency optimization using local workers
416    /// NOTE: Experimental
417    #[builder(default)]
418    pub enable_eager_workflow_start: bool,
419
420    /// Optionally set a retry policy for the workflow
421    #[builder(into)]
422    pub retry_policy: Option<RetryPolicy>,
423
424    /// If set, send a signal to the workflow atomically with start.
425    /// The workflow will receive this signal before its first task.
426    pub start_signal: Option<WorkflowStartSignal>,
427
428    /// Links to associate with the workflow. Ex: References to a nexus operation.
429    #[builder(default)]
430    pub links: Vec<common::v1::Link>,
431
432    /// Callbacks that will be invoked upon workflow completion. For, ex, completing nexus
433    /// operations.
434    #[builder(default)]
435    pub completion_callbacks: Vec<common::v1::Callback>,
436
437    /// Priority for the workflow. Defaults to all-inherited (empty).
438    #[builder(default)]
439    pub priority: Priority,
440
441    /// Headers to include with the start request.
442    pub header: Option<Header>,
443
444    /// Single-line static summary for the workflow, shown in the Temporal UI.
445    pub static_summary: Option<String>,
446
447    /// Multi-line static details for the workflow, shown in the Temporal UI.
448    pub static_details: Option<String>,
449
450    /// Controls for the RPC used to start the workflow.
451    #[builder(default)]
452    pub rpc_options: RpcOptions,
453}
454
455/// A signal to send atomically when starting a workflow.
456/// Use with `WorkflowStartOptions::start_signal` to achieve signal-with-start behavior.
457#[derive(Debug, Clone, bon::Builder)]
458#[builder(start_fn = new, on(String, into))]
459#[non_exhaustive]
460pub struct WorkflowStartSignal {
461    /// Name of the signal to send.
462    #[builder(start_fn)]
463    pub signal_name: String,
464    /// Payload for the signal.
465    pub input: Option<Payloads>,
466    /// Headers for the signal.
467    pub header: Option<Header>,
468}
469
470pub use temporalio_common::Priority;
471
472/// Options for fetching workflow results
473#[derive(Debug, Clone, bon::Builder)]
474#[non_exhaustive]
475pub struct WorkflowGetResultOptions {
476    /// If true (the default), follows to the next workflow run in the execution chain while
477    /// retrieving results.
478    #[builder(default = true)]
479    pub follow_runs: bool,
480    /// Controls for each history RPC used to retrieve the result.
481    #[builder(default)]
482    pub rpc_options: RpcOptions,
483}
484impl Default for WorkflowGetResultOptions {
485    fn default() -> Self {
486        Self {
487            follow_runs: true,
488            rpc_options: RpcOptions::default(),
489        }
490    }
491}
492
493/// Options for starting a workflow update.
494#[derive(Debug, Clone, Default, bon::Builder)]
495#[non_exhaustive]
496pub struct WorkflowExecuteUpdateOptions {
497    /// Update ID for idempotency.
498    pub update_id: Option<String>,
499    /// Headers to include.
500    pub header: Option<Header>,
501    /// Controls for the start-update and poll-update RPCs.
502    #[builder(default)]
503    pub rpc_options: RpcOptions,
504}
505
506/// Options for sending a signal to a workflow.
507#[derive(Debug, Clone, Default, bon::Builder)]
508#[non_exhaustive]
509pub struct WorkflowSignalOptions {
510    /// Request ID for idempotency. If not provided, a UUID will be generated.
511    pub request_id: Option<String>,
512    /// Headers to include with the signal.
513    pub header: Option<Header>,
514    /// Controls for the signal RPC.
515    #[builder(default)]
516    pub rpc_options: RpcOptions,
517}
518
519/// Options for querying a workflow.
520#[derive(Debug, Clone, Default, bon::Builder)]
521#[non_exhaustive]
522pub struct WorkflowQueryOptions {
523    /// Query reject condition. Determines when the query should be rejected
524    /// based on workflow state.
525    pub reject_condition: Option<QueryRejectCondition>,
526    /// Headers to include with the query.
527    pub header: Option<Header>,
528    /// Controls for the query RPC.
529    #[builder(default)]
530    pub rpc_options: RpcOptions,
531}
532
533/// Options for cancelling a workflow.
534#[derive(Debug, Clone, Default, bon::Builder)]
535#[builder(on(String, into))]
536#[non_exhaustive]
537pub struct WorkflowCancelOptions {
538    /// Reason for cancellation.
539    #[builder(default)]
540    pub reason: String,
541    /// Request ID for idempotency. If not provided, a UUID will be generated.
542    pub request_id: Option<String>,
543    /// Controls for the cancellation RPC.
544    #[builder(default)]
545    pub rpc_options: RpcOptions,
546}
547
548/// Options for terminating a workflow.
549#[derive(Debug, Clone, Default, bon::Builder)]
550#[builder(on(String, into))]
551#[non_exhaustive]
552pub struct WorkflowTerminateOptions {
553    /// Reason for termination.
554    #[builder(default)]
555    pub reason: String,
556    /// Additional details to include with the termination.
557    pub details: Option<Payloads>,
558    /// Controls for the termination RPC.
559    #[builder(default)]
560    pub rpc_options: RpcOptions,
561}
562
563/// Options for describing a workflow.
564#[derive(Debug, Clone, Default, bon::Builder)]
565#[non_exhaustive]
566pub struct WorkflowDescribeOptions {
567    /// Controls for the describe RPC.
568    #[builder(default)]
569    pub rpc_options: RpcOptions,
570}
571
572/// Default workflow execution retention for a Namespace is 3 days
573const DEFAULT_WORKFLOW_EXECUTION_RETENTION_PERIOD: Duration = Duration::from_secs(60 * 60 * 24 * 3);
574
575/// Helper struct for `register_namespace`.
576#[derive(Clone, Debug, bon::Builder)]
577#[builder(on(String, into))]
578#[non_exhaustive]
579pub struct RegisterNamespaceOptions {
580    /// Name (required)
581    pub namespace: String,
582    /// Description (required)
583    pub description: String,
584    /// Owner's email
585    #[builder(default)]
586    pub owner_email: String,
587    /// Workflow execution retention period
588    #[builder(default = DEFAULT_WORKFLOW_EXECUTION_RETENTION_PERIOD)]
589    pub workflow_execution_retention_period: Duration,
590    /// Cluster settings
591    #[builder(default)]
592    pub clusters: Vec<ClusterReplicationConfig>,
593    /// Active cluster name
594    #[builder(default)]
595    pub active_cluster_name: String,
596    /// Custom Data
597    #[builder(default)]
598    pub data: HashMap<String, String>,
599    /// Security Token
600    #[builder(default)]
601    pub security_token: String,
602    /// Global namespace
603    #[builder(default)]
604    pub is_global_namespace: bool,
605    /// History Archival setting
606    #[builder(default = ArchivalState::Unspecified)]
607    pub history_archival_state: ArchivalState,
608    /// History Archival uri
609    #[builder(default)]
610    pub history_archival_uri: String,
611    /// Visibility Archival setting
612    #[builder(default = ArchivalState::Unspecified)]
613    pub visibility_archival_state: ArchivalState,
614    /// Visibility Archival uri
615    #[builder(default)]
616    pub visibility_archival_uri: String,
617}
618
619impl From<RegisterNamespaceOptions> for RegisterNamespaceRequest {
620    fn from(val: RegisterNamespaceOptions) -> Self {
621        RegisterNamespaceRequest {
622            namespace: val.namespace,
623            description: val.description,
624            owner_email: val.owner_email,
625            workflow_execution_retention_period: val
626                .workflow_execution_retention_period
627                .try_into()
628                .ok(),
629            clusters: val.clusters,
630            active_cluster_name: val.active_cluster_name,
631            data: val.data,
632            security_token: val.security_token,
633            is_global_namespace: val.is_global_namespace,
634            history_archival_state: val.history_archival_state as i32,
635            history_archival_uri: val.history_archival_uri,
636            visibility_archival_state: val.visibility_archival_state as i32,
637            visibility_archival_uri: val.visibility_archival_uri,
638        }
639    }
640}
641
642/// Options for fetching workflow history.
643#[derive(Debug, Clone, Default, bon::Builder)]
644#[non_exhaustive]
645pub struct WorkflowFetchHistoryOptions {
646    /// Whether to skip archival.
647    #[builder(default)]
648    pub skip_archival: bool,
649    /// If set true, the fetch will wait for a new event before returning.
650    #[builder(default)]
651    pub wait_new_event: bool,
652    /// Specifies which kind of events will be retrieved. Defaults to all events.
653    #[builder(default = HistoryEventFilterType::AllEvent)]
654    pub event_filter_type: HistoryEventFilterType,
655    /// Controls for each history page RPC.
656    #[builder(default)]
657    pub rpc_options: RpcOptions,
658}
659
660/// Options for starting an update without waiting for completion.
661#[derive(Debug, Clone, Default, bon::Builder)]
662#[non_exhaustive]
663pub struct WorkflowStartUpdateOptions {
664    /// Update ID for idempotency. If not provided, a UUID will be generated.
665    pub update_id: Option<String>,
666    /// Headers to include with the update.
667    pub header: Option<Header>,
668    /// Controls for the start-update RPC.
669    #[builder(default)]
670    pub rpc_options: RpcOptions,
671}
672
673/// Options for listing workflows.
674#[derive(Debug, Clone, Default, bon::Builder)]
675#[non_exhaustive]
676pub struct WorkflowListOptions {
677    /// Maximum number of workflows to return.
678    /// If not specified, returns all matching workflows.
679    pub limit: Option<usize>,
680    /// Controls for each list page RPC.
681    #[builder(default)]
682    pub rpc_options: RpcOptions,
683}
684
685/// Options for counting workflows.
686#[derive(Debug, Clone, Default, bon::Builder)]
687#[non_exhaustive]
688pub struct WorkflowCountOptions {
689    /// Controls for the count RPC.
690    #[builder(default)]
691    pub rpc_options: RpcOptions,
692}
693
694/// Options for starting a standalone activity.
695#[derive(Clone, Debug, bon::Builder)]
696#[builder(start_fn = new, on(String, into))]
697#[non_exhaustive]
698pub struct ActivityStartOptions {
699    /// Task queue to run this activity on.
700    #[builder(start_fn)]
701    pub task_queue: String,
702    /// Activity ID of the started activity. It's recommended to use a meaningful business ID.
703    #[builder(start_fn)]
704    pub id: String,
705    /// Timeouts for activity completion.
706    ///
707    /// See [`ActivityCloseTimeouts`] for the meaning of each timeout variant.
708    #[builder(start_fn)]
709    pub close_timeouts: ActivityCloseTimeouts,
710    /// If set, specifies maximum time the activity can wait in the task queue before being picked
711    /// up by a worker. This timeout is non-retryable.
712    pub schedule_to_start_timeout: Option<Duration>,
713    /// If set, specifies maximum time between successful heartbeats.
714    pub heartbeat_timeout: Option<Duration>,
715    /// Controls how Activity is retried. If not set, the server will assign default retry policy.
716    #[builder(into)]
717    pub retry_policy: Option<RetryPolicy>,
718    /// Priority to use when starting this activity.
719    #[builder(default)]
720    pub priority: Priority,
721    /// Specifies behavior if there's a *closed* activity with the same ID.
722    #[builder(default)]
723    pub id_reuse_policy: ActivityIdReusePolicy,
724    /// Specifies behavior if there's a *running* activity with the same ID. Note that there can
725    /// only be one running activity for each Activity ID.
726    #[builder(default)]
727    pub id_conflict_policy: ActivityIdConflictPolicy,
728    /// Search attributes for the activity.
729    pub search_attributes: Option<SearchAttributes>,
730    /// Headers to include with the start request.
731    pub header: Option<Header>,
732    /// Single-line static summary for the activity, shown in the Temporal UI.
733    pub summary: Option<String>,
734    /// Multi-line static details for the activity, shown in the Temporal UI.
735    pub static_details: Option<String>,
736    /// Time to wait before dispatching the first activity task.
737    /// This delay is not applied to retry attempts.
738    pub start_delay: Option<Duration>,
739}
740
741impl ActivityStartOptions {
742    /// Returns a builder with `close_timeouts` set to [`ActivityCloseTimeouts::StartToClose`].
743    pub fn with_start_to_close_timeout(
744        task_queue: impl Into<String>,
745        activity_id: impl Into<String>,
746        start_to_close_timeout: Duration,
747    ) -> ActivityStartOptionsBuilder {
748        Self::new(
749            task_queue,
750            activity_id,
751            ActivityCloseTimeouts::StartToClose(start_to_close_timeout),
752        )
753    }
754
755    /// Returns a builder with `close_timeouts` set to [`ActivityCloseTimeouts::ScheduleToClose`].
756    pub fn with_schedule_to_close_timeout(
757        task_queue: impl Into<String>,
758        activity_id: impl Into<String>,
759        schedule_to_close_timeout: Duration,
760    ) -> ActivityStartOptionsBuilder {
761        Self::new(
762            task_queue,
763            activity_id,
764            ActivityCloseTimeouts::ScheduleToClose(schedule_to_close_timeout),
765        )
766    }
767}
768
769/// Specifies behavior when starting a standalone activity if there's a *closed* activity with
770/// the same ID. See [`ActivityStartOptions::id_reuse_policy`].
771#[non_exhaustive]
772#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
773pub enum ActivityIdReusePolicy {
774    #[default]
775    /// Always allow starting an activity using the same activity ID. This is the default.
776    AllowDuplicate,
777    /// Allow starting an activity using the same ID only when the last execution did not complete
778    /// successfully.
779    AllowDuplicateFailedOnly,
780    /// Do not permit re-use of the ID for this activity.
781    RejectDuplicate,
782}
783
784impl From<ActivityIdReusePolicy> for ProtoActivityIdReusePolicy {
785    fn from(value: ActivityIdReusePolicy) -> Self {
786        match value {
787            ActivityIdReusePolicy::AllowDuplicate => Self::AllowDuplicate,
788            ActivityIdReusePolicy::AllowDuplicateFailedOnly => Self::AllowDuplicateFailedOnly,
789            ActivityIdReusePolicy::RejectDuplicate => Self::RejectDuplicate,
790        }
791    }
792}
793
794/// Specifies behavior when starting a standalone activity if there's a *running* activity with
795/// the same ID. See [`ActivityStartOptions::id_conflict_policy`].
796#[non_exhaustive]
797#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
798pub enum ActivityIdConflictPolicy {
799    #[default]
800    /// Don't start a new activity; instead return
801    /// [`StartActivityError::AlreadyStarted`](crate::errors::StartActivityError::AlreadyStarted).
802    Fail,
803    /// Don't start a new activity; instead return a handle for the running activity.
804    UseExisting,
805}
806
807impl From<ActivityIdConflictPolicy> for ProtoActivityIdConflictPolicy {
808    fn from(value: ActivityIdConflictPolicy) -> Self {
809        match value {
810            ActivityIdConflictPolicy::Fail => Self::Fail,
811            ActivityIdConflictPolicy::UseExisting => Self::UseExisting,
812        }
813    }
814}
815
816/// Options for listing activities.
817#[derive(Debug, Clone, Default, bon::Builder)]
818#[non_exhaustive]
819pub struct ActivityListOptions {}
820
821/// Options for counting activities.
822#[derive(Debug, Clone, Default, bon::Builder)]
823#[non_exhaustive]
824pub struct ActivityCountOptions {}
825
826/// Controls which optional fields will be requested in
827/// [`ActivityHandle::describe`](crate::ActivityHandle::describe) operation. The fields will be
828/// present in returned [`ActivityExecutionDescription`](crate::ActivityExecutionDescription),
829/// subject to data availability and server support.
830///
831/// Note that these fields contain payloads that can be arbitrarily large. It's recommended not to
832/// include them unless they're needed.
833#[derive(Debug, Clone, Default, bon::Builder)]
834#[non_exhaustive]
835pub struct ActivityDescribeOptions {
836    /// If set and the activity received input, the input will be included.
837    #[builder(default)]
838    pub include_input: bool,
839    /// If set and the activity is closed, the activity outcome will be included.
840    #[builder(default)]
841    pub include_outcome: bool,
842    /// If set and the activity sent heartbeat details, the heartbeat details will be included.
843    #[builder(default)]
844    pub include_heartbeat_details: bool,
845    /// If set and the activity has a failed attempt, the last failure will be included.
846    #[builder(default)]
847    pub include_last_failure: bool,
848}
849
850/// Options for [`ActivityHandle::cancel`](crate::ActivityHandle::cancel).
851#[derive(Debug, Clone, Default, bon::Builder)]
852#[builder(on(String, into))]
853#[non_exhaustive]
854pub struct ActivityCancelOptions {
855    /// Reason for cancellation. Can be empty.
856    #[builder(default)]
857    pub reason: String,
858}
859
860/// Options for [`ActivityHandle::terminate`](crate::ActivityHandle::terminate).
861#[derive(Debug, Clone, Default, bon::Builder)]
862#[builder(on(String, into))]
863#[non_exhaustive]
864pub struct ActivityTerminateOptions {
865    /// Reason for termination. Can be empty.
866    #[builder(default)]
867    pub reason: String,
868}