Skip to main content

horfimbor_eventsource/cache_db/
mod.rs

1//! handle the cache
2
3use std::marker::PhantomData;
4
5use thiserror::Error;
6
7use crate::Dto;
8use crate::model_key::ModelKey;
9use crate::repository::ModelWithPosition;
10
11#[cfg(feature = "cache-redis")]
12pub mod redis;
13
14/// `CacheDb` has only one purpose, reading and writing state somewhere
15pub trait CacheDb<S>: Clone + Send + Sync
16where
17    S: Dto,
18{
19    /// internal function to read from the db
20    ///
21    /// # Errors
22    ///
23    /// Will return `Err` if any error append when calling the DB.
24    fn get_from_db(&self, prefix: Option<&str>, key: &ModelKey) -> Result<Option<String>, DbError>;
25
26    /// internal function to write in the db
27    ///
28    /// # Errors
29    ///
30    /// Will return `Err` if any error append when calling the DB.
31    fn set_in_db(&self, prefix: Option<&str>, key: &ModelKey, state: String)
32    -> Result<(), DbError>;
33
34    /// public function to read the db
35    ///
36    /// # Errors
37    ///
38    /// Will return `Err` if any error append when calling the DB.
39    fn get(&self, prefix: Option<&str>, key: &ModelKey) -> Result<ModelWithPosition<S>, DbError> {
40        let data = self.get_from_db(prefix, key);
41
42        match data {
43            Ok(None) => Ok(ModelWithPosition::default()),
44            Ok(Some(value)) => {
45                Ok(serde_json::from_str(value.as_str()).map_err(DbError::SerdeJson)?)
46            }
47            Err(err) => Err(err),
48        }
49    }
50
51    /// public function to write in the db
52    ///
53    /// # Errors
54    ///
55    /// Will return `Err` if any error append when calling the DB.
56    fn set(
57        &self,
58        key: &ModelKey,
59        data: ModelWithPosition<S>,
60        prefix: Option<&str>,
61    ) -> Result<(), DbError> {
62        let s = serde_json::to_string(&data).map_err(DbError::SerdeJson)?;
63        self.set_in_db(prefix, key, s)
64    }
65}
66
67/// cache db can fail in multiple ways.
68#[derive(Error, Debug)]
69pub enum DbError {
70    /// data store disconnected
71    #[error("data store disconnected `{0}`")]
72    Disconnect(String),
73
74    /// internal error can be anything depending on the `cache_db`
75    #[error("internal `{0}`")]
76    Internal(String),
77
78    /// serde error while reading or writing the cache
79    #[error("corruptCache `{0}`")]
80    SerdeJson(#[from] serde_json::Error),
81}
82
83/// `NoCache` is a placeholder allowing quick development,
84/// not recommended for production usage
85#[derive(Clone)]
86pub struct NoCache<S> {
87    state: PhantomData<S>,
88}
89
90impl<S> NoCache<S> {
91    /// simple constructor
92    #[must_use]
93    pub const fn new() -> Self {
94        Self { state: PhantomData }
95    }
96}
97
98impl<S> Default for NoCache<S> {
99    fn default() -> Self {
100        Self::new()
101    }
102}
103
104impl<S> CacheDb<S> for NoCache<S>
105where
106    S: Dto,
107{
108    fn get_from_db(
109        &self,
110        _prefix: Option<&str>,
111        _key: &ModelKey,
112    ) -> Result<Option<String>, DbError> {
113        Ok(None)
114    }
115
116    fn set_in_db(
117        &self,
118        _prefix: Option<&str>,
119        _key: &ModelKey,
120        _state: String,
121    ) -> Result<(), DbError> {
122        Ok(())
123    }
124}