Skip to main content

temporalio_workflow/workflow_context/options/
nexus.rs

1use std::{collections::HashMap, time::Duration};
2
3use crate::WorkflowCancellationToken;
4use temporalio_common_wasm::protos::{
5    coresdk::{
6        nexus::NexusOperationCancellationType as ProtoNexusOperationCancellationType,
7        workflow_commands::{ScheduleNexusOperation, WorkflowCommand, workflow_command},
8    },
9    temporal::api::common::v1::Payload,
10};
11
12/// Controls when Nexus operation cancellation is reported to a workflow.
13#[derive(
14    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
15)]
16#[non_exhaustive]
17pub enum NexusOperationCancellationType {
18    /// Wait until cancellation has completed.
19    #[default]
20    WaitCancellationCompleted,
21    /// Do not request cancellation.
22    Abandon,
23    /// Request cancellation and report it immediately.
24    TryCancel,
25    /// Wait until the cancellation request is acknowledged.
26    WaitCancellationRequested,
27}
28
29impl From<NexusOperationCancellationType> for ProtoNexusOperationCancellationType {
30    fn from(value: NexusOperationCancellationType) -> Self {
31        match value {
32            NexusOperationCancellationType::WaitCancellationCompleted => {
33                Self::WaitCancellationCompleted
34            }
35            NexusOperationCancellationType::Abandon => Self::Abandon,
36            NexusOperationCancellationType::TryCancel => Self::TryCancel,
37            NexusOperationCancellationType::WaitCancellationRequested => {
38                Self::WaitCancellationRequested
39            }
40        }
41    }
42}
43
44impl From<ProtoNexusOperationCancellationType> for NexusOperationCancellationType {
45    fn from(value: ProtoNexusOperationCancellationType) -> Self {
46        match value {
47            ProtoNexusOperationCancellationType::WaitCancellationCompleted => {
48                Self::WaitCancellationCompleted
49            }
50            ProtoNexusOperationCancellationType::Abandon => Self::Abandon,
51            ProtoNexusOperationCancellationType::TryCancel => Self::TryCancel,
52            ProtoNexusOperationCancellationType::WaitCancellationRequested => {
53                Self::WaitCancellationRequested
54            }
55        }
56    }
57}
58
59/// Options for Nexus Operations
60#[derive(Debug, Clone, bon::Builder)]
61#[builder(on(String, into))]
62#[non_exhaustive]
63pub struct NexusOperationOptions {
64    /// Endpoint name, must exist in the endpoint registry or this command will fail.
65    pub endpoint: String,
66    /// Service name.
67    pub service: String,
68    /// Operation name.
69    pub operation: String,
70    /// Input for the operation. The server converts this into Nexus request content and the
71    /// appropriate content headers internally when sending the StartOperation request. On the
72    /// handler side, if it is also backed by Temporal, the content is transformed back to the
73    /// original Payload sent in this command.
74    pub input: Option<Payload>,
75    /// Schedule-to-close timeout for this operation.
76    /// Indicates how long the caller is willing to wait for operation completion.
77    /// Calls are retried internally by the server.
78    pub schedule_to_close_timeout: Option<Duration>,
79    /// Header to attach to the Nexus request.
80    /// Users are responsible for encrypting sensitive data in this header as it is stored in
81    /// workflow history and transmitted to external services as-is. This is useful for propagating
82    /// tracing information. Note these headers are not the same as Temporal headers on internal
83    /// activities and child workflows, these are transmitted to Nexus operations that may be
84    /// external and are not traditional payloads.
85    #[builder(default)]
86    pub nexus_header: HashMap<String, String>,
87    /// Cancellation type for the operation
88    pub cancellation_type: Option<NexusOperationCancellationType>,
89    /// Cancellation token for this operation. `None` inherits workflow cancellation.
90    pub cancellation_token: Option<WorkflowCancellationToken>,
91    /// Schedule-to-start timeout for this operation.
92    /// Indicates how long the caller is willing to wait for the operation to be started (or completed if synchronous)
93    /// by the handler. If the operation is not started within this timeout, it will fail with
94    /// TIMEOUT_TYPE_SCHEDULE_TO_START.
95    /// If not set or zero, no schedule-to-start timeout is enforced.
96    pub schedule_to_start_timeout: Option<Duration>,
97    /// Start-to-close timeout for this operation.
98    /// Indicates how long the caller is willing to wait for an asynchronous operation to complete after it has been
99    /// started. If the operation does not complete within this timeout after starting, it will fail with
100    /// TIMEOUT_TYPE_START_TO_CLOSE.
101    /// Only applies to asynchronous operations. Synchronous operations ignore this timeout.
102    /// If not set or zero, no start-to-close timeout is enforced.
103    pub start_to_close_timeout: Option<Duration>,
104}
105
106impl NexusOperationOptions {
107    pub(crate) fn into_command(self, seq: u32) -> WorkflowCommand {
108        workflow_command::Variant::ScheduleNexusOperation(ScheduleNexusOperation {
109            seq,
110            endpoint: self.endpoint,
111            service: self.service,
112            operation: self.operation,
113            input: self.input,
114            schedule_to_close_timeout: self
115                .schedule_to_close_timeout
116                .and_then(|duration| duration.try_into().ok()),
117            schedule_to_start_timeout: self
118                .schedule_to_start_timeout
119                .and_then(|duration| duration.try_into().ok()),
120            start_to_close_timeout: self
121                .start_to_close_timeout
122                .and_then(|duration| duration.try_into().ok()),
123            nexus_header: self.nexus_header,
124            cancellation_type: ProtoNexusOperationCancellationType::from(
125                self.cancellation_type
126                    .unwrap_or(NexusOperationCancellationType::WaitCancellationCompleted),
127            )
128            .into(),
129        })
130        .into()
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137
138    #[test]
139    fn cancellation_defaults_to_wait_for_completion() {
140        assert_eq!(
141            NexusOperationCancellationType::default(),
142            NexusOperationCancellationType::WaitCancellationCompleted
143        );
144    }
145}