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::entry::{
96 ExecutableAsyncSignal, ExecutableAsyncUpdate, ExecutableQuery, ExecutableSyncSignal,
97 ExecutableSyncUpdate, WorkflowError, WorkflowImplementation, serialize_result,
98};
99
100/// Deterministic `join_all` for use in Temporal workflows.
101///
102/// Polls a collection of futures concurrently to completion in declaration order,
103/// returning a `Vec` of their results.
104///
105/// # Example
106///
107/// ```ignore
108/// use temporalio_sdk::workflows::join_all;
109/// use temporalio_sdk::WorkflowContext;
110/// use std::time::Duration;
111///
112/// # async fn hidden(ctx: &mut WorkflowContext<()>) {
113/// let timers = vec![
114/// ctx.timer(Duration::from_secs(1)),
115/// ctx.timer(Duration::from_secs(2)),
116/// ];
117/// let results = join_all(timers).await;
118/// # }
119/// ```
120pub fn join_all<I>(iter: I) -> JoinAll<I::Item>
121where
122 I: IntoIterator,
123 I::Item: std::future::Future,
124{
125 JoinAll(SdkGuardedFuture(futures_util::future::join_all(iter)))
126}
127
128/// Future returned by [`join_all`].
129pub struct JoinAll<F: std::future::Future>(SdkGuardedFuture<futures_util::future::JoinAll<F>>);
130
131impl<F: std::future::Future> std::future::Future for JoinAll<F> {
132 type Output = Vec<F::Output>;
133
134 fn poll(
135 mut self: std::pin::Pin<&mut Self>,
136 cx: &mut std::task::Context<'_>,
137 ) -> std::task::Poll<Self::Output> {
138 self.0.poll_unpin(cx)
139 }
140}