charybdis/
callbacks.rs

1use scylla::client::caching_session::CachingSession;
2use scylla::serialize::row::SerializeRow;
3
4use crate::errors::CharybdisError;
5use crate::model::Model;
6use crate::query::QueryValue;
7
8/// Callbacks are simple trait that can be implemented to add custom logic to the
9/// insert, update and delete operations. It's a way to wrap business logic in models.
10/// Usually, `before_<action>` callbacks are used to validate the data and set default values, while
11/// `after_<action>` callbacks are used to perform additional async operations, like populating elasticsearch client,
12/// sending messages to kafka, etc.
13/// In case one doesn't need extension it can be set to `Option<()>` and then
14/// it can be set to `None` when calling the operation.
15pub trait Callbacks: Model + 'static
16where
17    Self: 'static,
18{
19    type Extension;
20    type Error: From<CharybdisError>;
21
22    async fn before_insert(
23        &mut self,
24        _session: &CachingSession,
25        _extension: &Self::Extension,
26    ) -> Result<(), Self::Error> {
27        Ok(())
28    }
29
30    async fn after_insert(
31        &mut self,
32        _session: &CachingSession,
33        _extension: &Self::Extension,
34    ) -> Result<(), Self::Error> {
35        Ok(())
36    }
37
38    async fn before_update(
39        &mut self,
40        _session: &CachingSession,
41        _extension: &Self::Extension,
42    ) -> Result<(), Self::Error> {
43        Ok(())
44    }
45
46    async fn after_update(
47        &mut self,
48        _session: &CachingSession,
49        _extension: &Self::Extension,
50    ) -> Result<(), Self::Error> {
51        Ok(())
52    }
53
54    async fn before_delete(
55        &mut self,
56        _session: &CachingSession,
57        _extension: &Self::Extension,
58    ) -> Result<(), Self::Error> {
59        Ok(())
60    }
61
62    async fn after_delete(
63        &mut self,
64        _session: &CachingSession,
65        _extension: &Self::Extension,
66    ) -> Result<(), Self::Error> {
67        Ok(())
68    }
69}
70
71// The compiler issues warnings about potential cycles in the code due to callbacks when attempting to associate
72// operations with callbacks in CharybdisCbQuery::execute.
73// To circumvent these warnings and clearly delineate callback actions,
74// it's necessary to employ distinct structs for each callback operation.
75pub struct InsertAction<M: Callbacks>(M);
76pub struct UpdateAction<M: Callbacks>(M);
77pub struct DeleteAction<M: Callbacks>(M);
78
79pub trait CallbackAction<M: Callbacks> {
80    fn query_value<Val: SerializeRow>(model: &M) -> QueryValue<'_, Val, M>;
81
82    async fn before_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error>;
83
84    async fn after_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error>;
85}
86
87impl<M: Callbacks> CallbackAction<M> for InsertAction<M> {
88    fn query_value<Val: SerializeRow>(model: &'_ M) -> QueryValue<'_, Val, M> {
89        QueryValue::Model(model)
90    }
91
92    async fn before_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
93        model.before_insert(session, extension).await
94    }
95
96    async fn after_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
97        model.after_insert(session, extension).await
98    }
99}
100
101impl<M: Callbacks> CallbackAction<M> for UpdateAction<M> {
102    fn query_value<Val: SerializeRow>(model: &'_ M) -> QueryValue<'_, Val, M> {
103        QueryValue::Model(model)
104    }
105
106    async fn before_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
107        model.before_update(session, extension).await
108    }
109
110    async fn after_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
111        model.after_update(session, extension).await
112    }
113}
114
115impl<M: Callbacks> CallbackAction<M> for DeleteAction<M> {
116    fn query_value<Val: SerializeRow>(model: &'_ M) -> QueryValue<'_, Val, M> {
117        QueryValue::PrimaryKey(model.primary_key_values())
118    }
119
120    async fn before_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
121        model.before_delete(session, extension).await
122    }
123
124    async fn after_execute(model: &mut M, session: &CachingSession, extension: &M::Extension) -> Result<(), M::Error> {
125        model.after_delete(session, extension).await
126    }
127}