Skip to main content

runifold_effect/
handler.rs

1use std::{future::Future, pin::Pin, time::Instant};
2
3use runifold_core::{CancellationToken, EffectRequest, RunContext, RunError, RunId};
4use serde_json::Value;
5
6/// Boxed future returned by an effect handler.
7pub type EffectFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
8
9/// Lifecycle-only context passed to an external-effect handler.
10#[derive(Clone, Debug)]
11pub struct EffectExecutionContext {
12    run_id: RunId,
13    deadline: Option<Instant>,
14    cancellation: CancellationToken,
15}
16
17impl EffectExecutionContext {
18    pub(crate) fn for_run(run: &RunContext) -> Self {
19        Self {
20            run_id: run.run_id(),
21            deadline: run.deadline(),
22            cancellation: run.cancellation().child_token(),
23        }
24    }
25
26    /// Returns the owning Run identity.
27    pub const fn run_id(&self) -> RunId {
28        self.run_id
29    }
30
31    /// Returns the effective deadline.
32    pub const fn deadline(&self) -> Option<Instant> {
33        self.deadline
34    }
35
36    /// Returns the descendant cancellation token.
37    pub const fn cancellation(&self) -> &CancellationToken {
38        &self.cancellation
39    }
40}
41
42/// Object-safe implementation boundary for one class of external effect.
43pub trait EffectHandler: Send + Sync {
44    /// Executes a prepared effect request.
45    fn execute(
46        &self,
47        request: &EffectRequest,
48        context: EffectExecutionContext,
49    ) -> EffectFuture<'_, Result<Value, RunError>>;
50}