sayiir_runtime/runner/ext.rs
1use super::WorkflowRunner;
2use crate::error::RuntimeError;
3use crate::runner::in_process::InProcessRunner;
4use sayiir_core::codec::sealed;
5use sayiir_core::codec::{Codec, EnvelopeCodec};
6use sayiir_core::workflow::{Workflow, WorkflowStatus};
7
8/// Extension trait providing convenience methods on [`Workflow`].
9///
10/// # Caveats
11///
12/// This trait uses [`InProcessRunner`] under the hood, which means:
13/// - **No checkpointing** — workflow state is not persisted between steps.
14/// - **No crash recovery** — if the process dies, progress is lost.
15/// - **No distributed execution** — everything runs in the current process.
16///
17/// For production use with durability guarantees, use a [`WorkflowRunner`]
18/// backed by a persistence backend (e.g. `PostgreSQL`) instead.
19pub trait WorkflowRunExt<C, Input, M> {
20 /// Run the workflow once in-process without persistence.
21 ///
22 /// Uses [`InProcessRunner`] internally — no backend, no instance ID.
23 /// Ideal for quick testing and simple scripts.
24 ///
25 /// # Example
26 ///
27 /// ```rust,no_run
28 /// # use sayiir_runtime::prelude::*;
29 /// # use sayiir_core::error::BoxError;
30 /// # async fn example() -> Result<(), BoxError> {
31 /// let ctx = WorkflowContext::new("demo", std::sync::Arc::new(JsonCodec), std::sync::Arc::new(()));
32 /// let workflow = WorkflowBuilder::new(ctx)
33 /// .then("greet", |name: String| async move { Ok(format!("Hello, {name}!")) })
34 /// .build()?;
35 ///
36 /// let status = workflow.run_once("World".to_string()).await?;
37 /// # Ok(())
38 /// # }
39 /// ```
40 fn run_once(
41 &self,
42 input: Input,
43 ) -> impl std::future::Future<Output = Result<WorkflowStatus, RuntimeError>> + Send + '_
44 where
45 Input: Send + 'static,
46 M: Send + Sync + 'static,
47 C: Codec + EnvelopeCodec + sealed::EncodeValue<Input>;
48}
49
50impl<C, Input, M> WorkflowRunExt<C, Input, M> for Workflow<C, Input, M> {
51 fn run_once(
52 &self,
53 input: Input,
54 ) -> impl std::future::Future<Output = Result<WorkflowStatus, RuntimeError>> + Send + '_
55 where
56 Input: Send + 'static,
57 M: Send + Sync + 'static,
58 C: Codec + EnvelopeCodec + sealed::EncodeValue<Input>,
59 {
60 InProcessRunner.run(self, input)
61 }
62}