Skip to main content

plexor_core/
reactant.rs

1// Copyright 2025 Alecks Gates
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use crate::codec::{Codec, CodecName};
8use crate::erasure::reactant::{ErrorReactantErased, ReactantErased, ReactantRawErased};
9use crate::payload::{Payload, PayloadRaw};
10use std::future::Future;
11use std::pin::Pin;
12use std::sync::Arc;
13use thiserror::Error;
14
15#[derive(Error, Debug)]
16pub enum ReactantError {
17    #[error("Reactant execution failed: {0}")]
18    Execution(String),
19    #[error(transparent)]
20    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
21}
22
23pub trait Reactant<T, C>
24where
25    C: Codec<T> + CodecName + Send + Sync + 'static,
26    T: Send + Sync + 'static,
27    Self: Send + Sync,
28{
29    fn react(
30        &self,
31        payload: Arc<Payload<T, C>>,
32    ) -> Pin<Box<dyn Future<Output = Result<(), ReactantError>> + Send + 'static>>;
33
34    fn erase(self: Box<Self>) -> Arc<dyn ReactantErased + Send + Sync + 'static>;
35
36    /// Helper to consume this reactant and return an erased Arc.
37    fn new_erased(self) -> Arc<dyn ReactantErased + Send + Sync + 'static>
38    where
39        Self: Sized + 'static,
40    {
41        Box::new(self).erase()
42    }
43}
44
45pub trait ReactantRaw<T, C>
46where
47    C: Codec<T> + CodecName + Send + Sync + 'static,
48    T: Send + Sync + 'static,
49    Self: Send + Sync,
50{
51    fn react(
52        &self,
53        payload: Arc<PayloadRaw<T, C>>,
54    ) -> Pin<Box<dyn Future<Output = Result<(), ReactantError>> + Send + 'static>>;
55
56    fn erase_raw(self: Box<Self>) -> Arc<dyn ReactantRawErased + Send + Sync + 'static>;
57
58    /// Helper to consume this reactant and return an erased Arc.
59    fn new_erased_raw(self) -> Arc<dyn ReactantRawErased + Send + Sync + 'static>
60    where
61        Self: Sized + 'static,
62    {
63        Box::new(self).erase_raw()
64    }
65}
66
67pub trait ErrorReactant<T, C>: Send + Sync
68where
69    C: Codec<T> + CodecName + Send + Sync + 'static,
70    T: Send + Sync + 'static,
71{
72    fn react_error(
73        &self,
74        error: Arc<ReactantError>,
75        payload: Arc<Payload<T, C>>,
76    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
77
78    fn erase_error(self: Box<Self>) -> Arc<dyn ErrorReactantErased + Send + Sync + 'static>;
79
80    /// Helper to consume this error reactant and return an erased Arc.
81    fn new_erased_error(self) -> Arc<dyn ErrorReactantErased + Send + Sync + 'static>
82    where
83        Self: Sized + 'static,
84    {
85        Box::new(self).erase_error()
86    }
87}