runifold_effect/
handler.rs1use std::{future::Future, pin::Pin};
2
3use runifold_core::{CancellationToken, EffectRequest, Instant, RunContext, RunError, RunId};
4use serde_json::Value;
5
6#[cfg(not(target_arch = "wasm32"))]
8pub type EffectFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
9
10#[cfg(target_arch = "wasm32")]
12pub type EffectFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
13
14#[derive(Clone, Debug)]
16pub struct EffectExecutionContext {
17 run_id: RunId,
18 deadline: Option<Instant>,
19 cancellation: CancellationToken,
20}
21
22impl EffectExecutionContext {
23 pub(crate) fn for_run(run: &RunContext) -> Self {
24 Self {
25 run_id: run.run_id(),
26 deadline: run.deadline(),
27 cancellation: run.cancellation().child_token(),
28 }
29 }
30
31 pub const fn run_id(&self) -> RunId {
33 self.run_id
34 }
35
36 pub const fn deadline(&self) -> Option<Instant> {
38 self.deadline
39 }
40
41 pub const fn cancellation(&self) -> &CancellationToken {
43 &self.cancellation
44 }
45}
46
47pub trait EffectHandler: Send + Sync {
49 fn execute(
51 &self,
52 request: &EffectRequest,
53 context: EffectExecutionContext,
54 ) -> EffectFuture<'_, Result<Value, RunError>>;
55}
56
57#[derive(Clone, Debug, PartialEq)]
59#[non_exhaustive]
60pub enum EffectReconciliation {
61 Completed(Value),
63 NotExecuted,
65 Ambiguous,
67}
68
69pub trait EffectReconciler: Send + Sync {
74 fn reconcile(
76 &self,
77 request: &EffectRequest,
78 context: EffectExecutionContext,
79 ) -> EffectFuture<'_, Result<EffectReconciliation, RunError>>;
80}