Skip to main content

temporalio_workflow/workflow_context/
view.rs

1use super::{WorkflowRandomState, WorkflowRandomStream, WorkflowRandomStreamSource};
2use std::{
3    cell::RefCell,
4    rc::Rc,
5    time::{Duration, SystemTime},
6};
7
8use temporalio_common_wasm::{
9    Memo, Priority, RetryPolicy, WorkflowExecution,
10    data_converters::{PayloadConverter, SerializationContextData, WorkflowSerializationContext},
11    protos::coresdk::{
12        common::NamespacedWorkflowExecution, workflow_activation::InitializeWorkflow,
13    },
14    search_attributes::SearchAttributes,
15};
16
17/// Read-only view of workflow context for use in init and query handlers.
18///
19/// This provides access to workflow information but cannot issue commands.
20#[derive(Clone, Debug)]
21#[non_exhaustive]
22pub struct WorkflowContextView {
23    raw: InitializeWorkflow,
24    namespace: String,
25    task_queue: String,
26    run_id: String,
27    payload_converter: PayloadConverter,
28    requires_replay_safety: bool,
29    workflow_random: Option<Rc<RefCell<WorkflowRandomState>>>,
30}
31
32impl WorkflowContextView {
33    /// Create a new view from workflow initialization data.
34    pub(crate) fn new(
35        namespace: String,
36        task_queue: String,
37        run_id: String,
38        raw: InitializeWorkflow,
39        payload_converter: PayloadConverter,
40        requires_replay_safety: bool,
41        workflow_random: Option<Rc<RefCell<WorkflowRandomState>>>,
42    ) -> Self {
43        Self {
44            raw,
45            namespace,
46            task_queue,
47            run_id,
48            payload_converter,
49            requires_replay_safety,
50            workflow_random,
51        }
52    }
53
54    pub(super) fn into_parts(self) -> (String, String, String, InitializeWorkflow) {
55        (self.namespace, self.task_queue, self.run_id, self.raw)
56    }
57
58    /// Returns the workflow's unique identifier.
59    pub fn workflow_id(&self) -> &str {
60        &self.raw.workflow_id
61    }
62
63    /// Returns the run ID of this workflow execution.
64    pub fn run_id(&self) -> &str {
65        &self.run_id
66    }
67
68    /// Returns the workflow type name.
69    pub fn workflow_type(&self) -> &str {
70        &self.raw.workflow_type
71    }
72
73    /// Returns the task queue this workflow is executing on.
74    pub fn task_queue(&self) -> &str {
75        &self.task_queue
76    }
77
78    /// Returns the namespace this workflow is executing in.
79    pub fn namespace(&self) -> &str {
80        &self.namespace
81    }
82
83    /// Returns the current attempt number, starting from one.
84    pub fn attempt(&self) -> u32 {
85        self.raw.attempt as u32
86    }
87
88    /// Returns the run ID of the first execution in the chain.
89    pub fn first_execution_run_id(&self) -> &str {
90        &self.raw.first_execution_run_id
91    }
92
93    /// Returns the run ID of the previous execution when this is a continuation.
94    pub fn continued_from_run_id(&self) -> Option<&str> {
95        (!self.raw.continued_from_execution_run_id.is_empty())
96            .then_some(self.raw.continued_from_execution_run_id.as_str())
97    }
98
99    /// Returns when the workflow execution started.
100    pub fn start_time(&self) -> Option<SystemTime> {
101        self.raw.start_time.and_then(|time| time.try_into().ok())
102    }
103
104    /// Returns the total workflow execution timeout, including retries and continue-as-new.
105    pub fn execution_timeout(&self) -> Option<Duration> {
106        self.raw
107            .workflow_execution_timeout
108            .and_then(|timeout| timeout.try_into().ok())
109    }
110
111    /// Returns the timeout of a single workflow run.
112    pub fn run_timeout(&self) -> Option<Duration> {
113        self.raw
114            .workflow_run_timeout
115            .and_then(|timeout| timeout.try_into().ok())
116    }
117
118    /// Returns the timeout of a single workflow task.
119    pub fn task_timeout(&self) -> Option<Duration> {
120        self.raw
121            .workflow_task_timeout
122            .and_then(|timeout| timeout.try_into().ok())
123    }
124
125    /// Returns information about the parent workflow when this is a child workflow.
126    pub fn parent(&self) -> Option<NamespacedWorkflowInfo> {
127        self.raw
128            .parent_workflow_info
129            .clone()
130            .map(NamespacedWorkflowInfo::from_raw)
131    }
132
133    /// Returns information about the root workflow in the execution chain.
134    pub fn root(&self) -> Option<WorkflowExecution> {
135        self.raw.root_workflow.clone().map(Into::into)
136    }
137
138    /// Returns the workflow's retry policy.
139    pub fn retry_policy(&self) -> Option<RetryPolicy> {
140        self.raw.retry_policy.clone().map(Into::into)
141    }
142
143    /// Returns the cron schedule when this workflow runs on one.
144    pub fn cron_schedule(&self) -> Option<&str> {
145        (!self.raw.cron_schedule.is_empty()).then_some(self.raw.cron_schedule.as_str())
146    }
147
148    /// Returns priority and fairness configuration for this workflow execution.
149    pub fn priority(&self) -> Priority {
150        self.raw.priority.clone().unwrap_or_default().into()
151    }
152
153    /// Returns user-defined memo values.
154    pub fn memo(&self) -> Memo {
155        Memo::from_raw(
156            self.raw.memo.clone(),
157            self.payload_converter.clone(),
158            SerializationContextData::Workflow(WorkflowSerializationContext::new()),
159        )
160    }
161
162    /// Returns initial search attributes as a typed collection.
163    pub fn search_attributes(&self) -> Option<SearchAttributes> {
164        self.raw
165            .search_attributes
166            .as_ref()
167            .map(SearchAttributes::from_proto)
168    }
169
170    #[allow(
171        dead_code,
172        reason = "used by SDK-provided interceptors built separately from this change"
173    )]
174    pub(crate) fn random_stream(&self, name: impl Into<String>) -> WorkflowRandomStream {
175        let source = if self.requires_replay_safety {
176            WorkflowRandomStreamSource::Workflow(
177                self.workflow_random
178                    .clone()
179                    .expect("replay-safe context views must have workflow randomness"),
180            )
181        } else {
182            super::system_random_stream_source()
183        };
184        WorkflowRandomStream {
185            source,
186            name: name.into(),
187        }
188    }
189
190    /// Accesses the underlying workflow initialization protobuf.
191    pub fn raw(&self) -> &InitializeWorkflow {
192        &self.raw
193    }
194
195    /// Consumes this view and returns the underlying workflow initialization protobuf.
196    pub fn into_raw(self) -> InitializeWorkflow {
197        self.raw
198    }
199}
200
201/// Information about a parent workflow.
202#[derive(Clone, Debug)]
203#[non_exhaustive]
204pub struct NamespacedWorkflowInfo {
205    raw: NamespacedWorkflowExecution,
206}
207
208impl NamespacedWorkflowInfo {
209    fn from_raw(raw: NamespacedWorkflowExecution) -> Self {
210        Self { raw }
211    }
212
213    /// Returns the parent workflow's unique identifier.
214    pub fn workflow_id(&self) -> &str {
215        &self.raw.workflow_id
216    }
217
218    /// Returns the parent workflow's run ID.
219    pub fn run_id(&self) -> &str {
220        &self.raw.run_id
221    }
222
223    /// Returns the parent workflow's namespace.
224    pub fn namespace(&self) -> &str {
225        &self.raw.namespace
226    }
227
228    /// Accesses the underlying parent workflow protobuf.
229    pub fn raw(&self) -> &NamespacedWorkflowExecution {
230        &self.raw
231    }
232
233    /// Consumes this wrapper and returns the underlying parent workflow protobuf.
234    pub fn into_raw(self) -> NamespacedWorkflowExecution {
235        self.raw
236    }
237}