use crate::coordinate::Coordinate;
use crate::event::{Event, EventKind, EventPayload};
mod sealed {
pub trait Sealed {}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ReplayLane {
Value,
RawMsgpack,
}
pub trait ProjectionInput: sealed::Sealed + Send + Sync + 'static {
type Payload: Clone + Send + Sync + 'static;
const MODE: ReplayLane;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct JsonValueInput;
impl sealed::Sealed for JsonValueInput {}
impl ProjectionInput for JsonValueInput {
type Payload = serde_json::Value;
const MODE: ReplayLane = ReplayLane::Value;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct RawMsgpackInput;
impl sealed::Sealed for RawMsgpackInput {}
impl ProjectionInput for RawMsgpackInput {
type Payload = Vec<u8>;
const MODE: ReplayLane = ReplayLane::RawMsgpack;
}
pub type ProjectionPayload<T> = <<T as EventSourced>::Input as ProjectionInput>::Payload;
pub type ProjectionEvent<T> = Event<ProjectionPayload<T>>;
pub trait EventSourced: Sized {
type Input: ProjectionInput;
fn from_events(events: &[ProjectionEvent<Self>]) -> Option<Self>;
fn apply_event(&mut self, event: &ProjectionEvent<Self>);
fn relevant_event_kinds() -> &'static [EventKind];
fn schema_version() -> u64 {
0
}
fn supports_incremental_apply() -> bool {
false
}
}
pub trait TypedReactive<T: EventPayload>: Send + 'static {
type Error: std::error::Error + Send + Sync + 'static;
fn react(
&mut self,
event: &crate::event::StoredEvent<T>,
out: &mut crate::store::ReactionBatch,
at_least_once: Option<&crate::store::AtLeastOnce>,
) -> Result<(), Self::Error>;
}
#[derive(Debug)]
pub enum MultiDispatchError<E: std::error::Error + Send + Sync + 'static> {
User(E),
Decode(crate::event::TypedDecodeError),
}
impl<E: std::error::Error + Send + Sync + 'static> std::fmt::Display for MultiDispatchError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::User(e) => write!(f, "multi-reactor user error: {e}"),
Self::Decode(e) => write!(f, "multi-reactor decode failure: {e}"),
}
}
}
impl<E: std::error::Error + Send + Sync + 'static> std::error::Error for MultiDispatchError<E> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::User(e) => Some(e),
Self::Decode(e) => Some(e),
}
}
}
pub trait MultiReactive<Input: ProjectionInput>: Send + 'static {
type Error: std::error::Error + Send + Sync + 'static;
fn relevant_event_kinds() -> &'static [EventKind];
fn dispatch(
&mut self,
event: &crate::event::StoredEvent<Input::Payload>,
out: &mut crate::store::ReactionBatch,
at_least_once: Option<&crate::store::AtLeastOnce>,
) -> Result<(), MultiDispatchError<Self::Error>>;
}
pub trait Reactive<P> {
fn react(&self, event: &Event<P>) -> Vec<(Coordinate, EventKind, P)>;
}