Skip to main content

aion_client/
handle.rs

1//! `WorkflowHandle` signal, query, cancel, describe, and subscribe support.
2
3use std::time::Duration;
4
5use aion_core::{Payload, RunId, WorkflowId};
6use serde::Serialize;
7use serde::de::DeserializeOwned;
8
9use crate::client::Client;
10use crate::error::ClientError;
11use crate::ops::WorkflowDescription;
12use crate::stream::EventStream;
13
14/// Handle for a concrete workflow run returned by [`Client::start`].
15#[derive(Clone)]
16pub struct WorkflowHandle {
17    client: Client,
18    workflow_id: WorkflowId,
19    run_id: RunId,
20}
21
22impl WorkflowHandle {
23    /// Constructs a handle from caller-held workflow and run identifiers.
24    ///
25    /// The `client` is retained so handle methods can delegate through the same
26    /// transport, error mapping, payload machinery, and stream implementation as
27    /// top-level [`Client`] operations.
28    #[must_use]
29    pub fn from_ids(client: Client, workflow_id: WorkflowId, run_id: RunId) -> Self {
30        Self {
31            client,
32            workflow_id,
33            run_id,
34        }
35    }
36
37    /// Returns the workflow identifier bundled in this handle.
38    #[must_use]
39    pub const fn workflow_id(&self) -> &WorkflowId {
40        &self.workflow_id
41    }
42
43    /// Returns the run identifier bundled in this handle.
44    #[must_use]
45    pub const fn run_id(&self) -> &RunId {
46        &self.run_id
47    }
48
49    /// Sends a raw payload signal to this concrete run.
50    ///
51    /// # Errors
52    ///
53    /// Returns [`ClientError`] when signal delivery fails.
54    pub async fn signal(
55        &self,
56        name: impl Into<String>,
57        payload: Payload,
58    ) -> Result<(), ClientError> {
59        self.client
60            .signal(&self.workflow_id, Some(&self.run_id), name, payload)
61            .await
62    }
63
64    /// Sends a JSON-typed signal to this concrete run.
65    ///
66    /// # Errors
67    ///
68    /// Returns [`ClientError::InvalidArgument`] when serialization fails, or the
69    /// delegated signal error otherwise.
70    pub async fn signal_typed<T>(
71        &self,
72        name: impl Into<String>,
73        value: &T,
74    ) -> Result<(), ClientError>
75    where
76        T: Serialize + ?Sized,
77    {
78        self.client
79            .signal_typed(&self.workflow_id, Some(&self.run_id), name, value)
80            .await
81    }
82
83    /// Queries this concrete run and returns a raw payload result.
84    ///
85    /// # Errors
86    ///
87    /// Returns [`ClientError`] when the query fails or times out.
88    pub async fn query(
89        &self,
90        name: impl Into<String>,
91        args: Payload,
92        deadline: Duration,
93    ) -> Result<Payload, ClientError> {
94        self.client
95            .query(&self.workflow_id, Some(&self.run_id), name, args, deadline)
96            .await
97    }
98
99    /// Queries this concrete run and deserializes the result to `R`.
100    ///
101    /// # Errors
102    ///
103    /// Returns [`ClientError::InvalidArgument`] when typed argument serialization
104    /// or result decoding fails, or the delegated query error otherwise.
105    pub async fn query_typed<A, R>(
106        &self,
107        name: impl Into<String>,
108        args: &A,
109        deadline: Duration,
110    ) -> Result<R, ClientError>
111    where
112        A: Serialize + ?Sized,
113        R: DeserializeOwned,
114    {
115        self.client
116            .query_typed(&self.workflow_id, Some(&self.run_id), name, args, deadline)
117            .await
118    }
119
120    /// Requests cancellation of this concrete run.
121    ///
122    /// # Errors
123    ///
124    /// Returns [`ClientError`] when the server rejects the cancellation request.
125    pub async fn cancel(&self, reason: impl Into<String>) -> Result<(), ClientError> {
126        self.client
127            .cancel(&self.workflow_id, Some(&self.run_id), reason)
128            .await
129    }
130
131    /// Describes this concrete run.
132    ///
133    /// # Errors
134    ///
135    /// Returns [`ClientError`] when the description cannot be fetched or decoded.
136    pub async fn describe(&self) -> Result<WorkflowDescription, ClientError> {
137        self.client
138            .describe(&self.workflow_id, Some(&self.run_id))
139            .await
140    }
141
142    /// Subscribes to events for this workflow.
143    #[must_use]
144    pub fn subscribe(&self) -> EventStream {
145        self.client.subscribe_workflow(&self.workflow_id)
146    }
147}
148
149impl PartialEq for WorkflowHandle {
150    fn eq(&self, other: &Self) -> bool {
151        self.workflow_id == other.workflow_id && self.run_id == other.run_id
152    }
153}
154
155impl Eq for WorkflowHandle {}
156
157impl std::fmt::Debug for WorkflowHandle {
158    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159        formatter
160            .debug_struct("WorkflowHandle")
161            .field("workflow_id", &self.workflow_id)
162            .field("run_id", &self.run_id)
163            .finish_non_exhaustive()
164    }
165}