temporalio_workflow/workflows.rs
1//! Functionality related to defining and interacting with workflows
2//!
3//! This module contains traits and types for implementing workflows using the
4//! `#[workflow]` and `#[workflow_methods]` macros.
5//!
6//! Example usage:
7//! ```
8//! use temporalio_macros::{workflow, workflow_methods};
9//! use temporalio_workflow::{
10//! SyncWorkflowContext, WorkflowContext, WorkflowContextView, WorkflowResult,
11//! };
12//!
13//! #[workflow]
14//! pub struct MyWorkflow {
15//! counter: u32,
16//! }
17//!
18//! #[workflow_methods]
19//! impl MyWorkflow {
20//! #[init]
21//! pub fn new(ctx: &WorkflowContextView, input: String) -> Self {
22//! Self { counter: 0 }
23//! }
24//!
25//! // Async run method uses ctx.state() for reading
26//! #[run]
27//! pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
28//! let counter = ctx.state(|s| s.counter);
29//! Ok(format!("Done with counter: {}", counter))
30//! }
31//!
32//! // Sync signals use &mut self for direct mutations
33//! #[signal]
34//! pub fn increment(&mut self, ctx: &mut SyncWorkflowContext<Self>, amount: u32) {
35//! self.counter += amount;
36//! }
37//!
38//! // Queries use &self with read-only context
39//! #[query]
40//! pub fn get_counter(&self, ctx: &WorkflowContextView) -> u32 {
41//! self.counter
42//! }
43//! }
44//! ```
45
46/// Deterministic `select!` for use in Temporal workflows.
47///
48/// Polls branches in declaration order (top to bottom), ensuring deterministic
49/// behavior across workflow replays. Delegates to [`futures_util::select_biased!`].
50///
51/// All workflow futures (timers, activities, child workflows, etc.) implement
52/// `FusedFuture`, so they can be stored in variables and passed to `select!`
53/// without needing `.fuse()`.
54///
55/// # Example
56///
57/// ```ignore
58/// use temporalio_sdk::workflows::select;
59/// use temporalio_sdk::WorkflowContext;
60/// use std::time::Duration;
61///
62/// # async fn hidden(ctx: &mut WorkflowContext<()>) {
63/// select! {
64/// _ = ctx.timer(Duration::from_secs(60)) => { /* timer fired */ }
65/// reason = ctx.cancelled() => { /* cancelled */ }
66/// };
67/// # }
68/// ```
69#[doc(inline)]
70pub use crate::__temporal_select as select;
71
72/// Deterministic `join!` for use in Temporal workflows.
73///
74/// Polls all futures concurrently to completion in declaration order,
75/// ensuring deterministic behavior across workflow replays. Delegates
76/// to [`futures_util::join!`].
77///
78/// # Example
79///
80/// ```ignore
81/// use temporalio_sdk::workflows::join;
82///
83/// # async fn hidden() {
84/// let future_a = async { 1 };
85/// let future_b = async { 2 };
86/// let (a, b) = join!(future_a, future_b);
87/// # }
88/// ```
89#[doc(inline)]
90pub use crate::__temporal_join as join;
91
92use crate::runtime::SdkGuardedFuture;
93use futures_util::FutureExt;
94
95pub use crate::runtime::{
96 entry::{
97 ExecutableAsyncSignal, ExecutableAsyncUpdate, ExecutableQuery, ExecutableSyncSignal,
98 ExecutableSyncUpdate, WorkflowError, WorkflowImplementation, serialize_result,
99 },
100 types::{UpdateDefinitionDescriptor, WorkflowDefinitionDescriptor},
101};
102
103/// Deterministic `join_all` for use in Temporal workflows.
104///
105/// Polls a collection of futures concurrently to completion in declaration order,
106/// returning a `Vec` of their results.
107///
108/// # Example
109///
110/// ```ignore
111/// use temporalio_sdk::workflows::join_all;
112/// use temporalio_sdk::WorkflowContext;
113/// use std::time::Duration;
114///
115/// # async fn hidden(ctx: &mut WorkflowContext<()>) {
116/// let timers = vec![
117/// ctx.timer(Duration::from_secs(1)),
118/// ctx.timer(Duration::from_secs(2)),
119/// ];
120/// let results = join_all(timers).await;
121/// # }
122/// ```
123pub fn join_all<I>(iter: I) -> JoinAll<I::Item>
124where
125 I: IntoIterator,
126 I::Item: std::future::Future,
127{
128 JoinAll(SdkGuardedFuture(futures_util::future::join_all(iter)))
129}
130
131/// Future returned by [`join_all`].
132pub struct JoinAll<F: std::future::Future>(SdkGuardedFuture<futures_util::future::JoinAll<F>>);
133
134impl<F: std::future::Future> std::future::Future for JoinAll<F> {
135 type Output = Vec<F::Output>;
136
137 fn poll(
138 mut self: std::pin::Pin<&mut Self>,
139 cx: &mut std::task::Context<'_>,
140 ) -> std::task::Poll<Self::Output> {
141 self.0.poll_unpin(cx)
142 }
143}