horfimbor_eventsource/
lib.rs

1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4use std::error::Error;
5use std::fmt::{Debug, Display, Formatter};
6
7/// re-export import :
8pub use horfimbor_eventsource_derive;
9use kurrentdb::Error as EventStoreError;
10use serde::Serialize;
11use serde::de::DeserializeOwned;
12use serde_json::Error as SerdeError;
13use thiserror::Error;
14use uuid::{Error as UuidError, Uuid};
15
16use crate::cache_db::DbError;
17use crate::model_key::ModelKey;
18
19pub mod cache_db;
20pub mod helper;
21pub mod metadata;
22pub mod model_key;
23pub mod repository;
24
25/// str wrapper
26pub type StreamName = &'static str;
27
28/// `Stream` allow to create a subscription for different kind.
29pub enum Stream {
30    /// subscribe to an entity
31    Model(ModelKey),
32    /// subscribe to all the event of a stream
33    Stream(StreamName),
34    /// subscribe to an event across entities
35    Event(EventName),
36    /// subscribe to all the descendant of a specific event
37    Correlation(Uuid),
38}
39
40impl Display for Stream {
41    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42        match self {
43            Self::Model(m) => {
44                write!(f, "{}", m.format())
45            }
46            Self::Stream(stream_name) => {
47                let n = stream_name.replace('-', "_");
48                write!(f, "$ce-{n}")
49            }
50            Self::Event(e) => {
51                write!(f, "$et-{e}")
52            }
53            Self::Correlation(u) => {
54                write!(f, "bc-{u}")
55            }
56        }
57    }
58}
59
60/// error for the repository
61#[derive(Error, Debug)]
62pub enum EventSourceError {
63    /// the cache is gone ?
64    #[error("Cache error")]
65    CacheDbError(#[from] DbError),
66
67    /// the db is gone ?
68    #[error("Event store error")]
69    EventStore(#[from] EventStoreError),
70
71    /// Bad position can append when race condition occur
72    /// this error is retryable
73    #[error("Event store position error : {0}")]
74    Position(String),
75
76    /// Error for serialization
77    #[error("Serde error")]
78    Serde(#[from] SerdeError),
79
80    /// Error when converting uuid
81    #[error("Uuid error")]
82    Uuid(#[from] UuidError),
83}
84
85/// error coming from the `StateRepository`
86#[derive(Error, Debug)]
87pub enum EventSourceStateError {
88    /// error from `EventSourceError`
89    #[error("Event source error")]
90    EventSourceError(#[from] EventSourceError),
91
92    /// error depending on the `State`
93    #[error("State error : {0}")]
94    State(String),
95}
96
97/// str wrapper
98pub type CommandName = &'static str;
99/// str wrapper
100pub type EventName = &'static str;
101/// str wrapper
102pub type StateName = &'static str;
103
104/// `Command` are an enum for all the action possible
105pub trait Command: Serialize + DeserializeOwned + Debug + Send + Clone {
106    /// the `CommandName` must be unique for each variant of the enum
107    fn command_name(&self) -> CommandName;
108}
109
110/// `Event` are an enum for all the change possible
111pub trait Event: Serialize + DeserializeOwned + Debug + Send + Clone {
112    /// the `EventName` must be unique for each variant of the enum
113    fn event_name(&self) -> EventName;
114}
115
116/// the `Dto` trait provide a reader on the database
117pub trait Dto: Default + Serialize + DeserializeOwned + Debug + Send + Clone + Sync {
118    /// Event is the enum for all possible change on the `Dto`
119    type Event: Event + Sync + Send;
120
121    /// events are played one by one
122    fn play_event(&mut self, event: &Self::Event);
123}
124
125/// `StateNamed` just provide a getter for the `StateName`
126pub trait StateNamed {
127    /// that's all
128    fn state_name() -> StateName;
129}
130
131/// the `State` trait add update to the state.
132pub trait State: Dto + StateNamed {
133    /// the command are all the possible operation on the State
134    type Command: Command + Sync + Send;
135
136    /// the error that can occurs from the command
137    type Error: Error + Sync + Send;
138
139    /// command can produce multiple events or an error if condition are not met
140    ///
141    /// # Errors
142    ///
143    /// Will return `Err` if Command cannot currently occur OR something is wrong with DB
144    fn try_command(&self, command: Self::Command) -> Result<Vec<Self::Event>, Self::Error>;
145}