1use super::QueryContext;
2use crate::{
3 Map,
4 error::Error,
5 model::{Model, Mutation, Query},
6};
7use std::borrow::Cow;
8
9pub trait ModelHooks: Model {
13 type Data: Default;
15 type Extension: Clone + Send + Sync + 'static;
17
18 #[inline]
20 async fn before_extract() -> Result<(), Error> {
21 Ok(())
22 }
23
24 #[inline]
26 async fn after_extract(&mut self, _extension: Self::Extension) -> Result<(), Error> {
27 Ok(())
28 }
29
30 #[inline]
32 async fn before_validation(
33 _model: &mut Map,
34 _extension: Option<&Self::Extension>,
35 ) -> Result<(), Error> {
36 Ok(())
37 }
38
39 #[inline]
41 async fn after_validation(&mut self, _model: &mut Map) -> Result<(), Error> {
42 Ok(())
43 }
44
45 #[inline]
47 async fn before_create_table() -> Result<(), Error> {
48 Ok(())
49 }
50
51 #[inline]
53 async fn after_create_table() -> Result<(), Error> {
54 Ok(())
55 }
56
57 #[inline]
60 async fn before_prepare(&self) -> Result<Option<String>, Error> {
61 Ok(None)
62 }
63
64 #[inline]
66 async fn before_scan(query: &str) -> Result<QueryContext, Error> {
67 let model_name = Self::model_name();
68 let ctx = QueryContext::new(model_name);
69 let query_id = ctx.query_id().to_string();
70 tracing::debug!(model_name, query_id, query);
71 Ok(ctx)
72 }
73
74 async fn after_scan(ctx: &QueryContext) -> Result<(), Error> {
76 let model_name = ctx.model_name();
77 let query_id = ctx.query_id().to_string();
78 let query = ctx.query();
79 let arguments = ctx.format_arguments();
80 let message = match ctx.rows_affected() {
81 Some(0) => Cow::Borrowed("no rows affected or fetched"),
82 Some(1) => Cow::Borrowed("only one row affected or fetched"),
83 Some(num_rows) if num_rows > 1 => {
84 Cow::Owned(format!("{num_rows} rows affected or fetched"))
85 }
86 _ => Cow::Borrowed("query result has not been recorded"),
87 };
88 let execution_time = ctx.start_time().elapsed();
89 let execution_time_millis = execution_time.as_millis();
90 tracing::info!(
91 model_name,
92 query_id,
93 query,
94 arguments,
95 execution_time_millis,
96 "{message}"
97 );
98 Ok(())
99 }
100
101 #[inline]
103 async fn before_insert_check(
104 &mut self,
105 _extension: Option<&Self::Extension>,
106 ) -> Result<(), Error> {
107 Ok(())
108 }
109
110 #[inline]
112 async fn before_insert(&mut self) -> Result<Self::Data, Error> {
113 self.before_save().await
114 }
115
116 #[inline]
118 async fn after_insert(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
119 Self::after_save(ctx, data).await?;
120 #[cfg(feature = "metrics")]
121 ctx.emit_metrics("insert");
122 Ok(())
123 }
124
125 #[inline]
127 async fn before_soft_delete(&mut self) -> Result<Self::Data, Error> {
128 self.before_save().await
129 }
130
131 #[inline]
133 async fn after_soft_delete(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
134 Self::after_save(ctx, data).await?;
135 #[cfg(feature = "metrics")]
136 ctx.emit_metrics("soft_delete");
137 Ok(())
138 }
139
140 #[inline]
142 async fn before_lock(&mut self) -> Result<Self::Data, Error> {
143 self.before_save().await
144 }
145
146 #[inline]
148 async fn after_lock(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
149 Self::after_save(ctx, data).await?;
150 #[cfg(feature = "metrics")]
151 ctx.emit_metrics("lock");
152 Ok(())
153 }
154
155 #[inline]
157 async fn before_archive(&mut self) -> Result<Self::Data, Error> {
158 self.before_save().await
159 }
160
161 #[inline]
163 async fn after_archive(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
164 Self::after_save(ctx, data).await?;
165 #[cfg(feature = "metrics")]
166 ctx.emit_metrics("archive");
167 Ok(())
168 }
169
170 #[inline]
172 async fn before_update(&mut self) -> Result<Self::Data, Error> {
173 self.before_save().await
174 }
175
176 #[inline]
178 async fn after_update(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
179 Self::after_save(ctx, data).await?;
180 #[cfg(feature = "metrics")]
181 ctx.emit_metrics("update");
182 Ok(())
183 }
184
185 #[inline]
187 async fn before_upsert(&mut self) -> Result<Self::Data, Error> {
188 self.before_save().await
189 }
190
191 #[inline]
193 async fn after_upsert(ctx: &QueryContext, data: Self::Data) -> Result<(), Error> {
194 Self::after_save(ctx, data).await?;
195 #[cfg(feature = "metrics")]
196 ctx.emit_metrics("upsert");
197 Ok(())
198 }
199
200 #[inline]
202 async fn before_save(&mut self) -> Result<Self::Data, Error> {
203 Ok(Self::Data::default())
204 }
205
206 #[inline]
208 async fn after_save(ctx: &QueryContext, _data: Self::Data) -> Result<(), Error> {
209 if !ctx.is_success() {
210 ctx.record_error("fail to save a model into the table");
211 }
212 Ok(())
213 }
214
215 #[inline]
217 async fn before_delete(&mut self) -> Result<Self::Data, Error> {
218 Ok(Self::Data::default())
219 }
220
221 #[inline]
223 async fn after_delete(self, ctx: &QueryContext, _data: Self::Data) -> Result<(), Error> {
224 let query = ctx.query();
225 let query_id = ctx.query_id().to_string();
226 if ctx.is_success() {
227 tracing::warn!(query, query_id, "a model was deleted from the table");
228 } else {
229 tracing::error!(query, query_id, "fail to detele a model from the table");
230 }
231 #[cfg(feature = "metrics")]
232 ctx.emit_metrics("delete");
233 Ok(())
234 }
235
236 #[inline]
238 async fn before_count(_query: &Query) -> Result<(), Error> {
239 Ok(())
240 }
241
242 #[inline]
244 async fn after_count(ctx: &QueryContext) -> Result<(), Error> {
245 if !ctx.is_success() {
246 ctx.record_error("fail to count the models in the table");
247 }
248 #[cfg(feature = "metrics")]
249 ctx.emit_metrics("count");
250 Ok(())
251 }
252
253 #[inline]
255 async fn before_aggregate(_query: &Query) -> Result<(), Error> {
256 Ok(())
257 }
258
259 #[inline]
261 async fn after_aggregate(ctx: &QueryContext) -> Result<(), Error> {
262 if !ctx.is_success() {
263 ctx.record_error("fail to aggregate the models in the table");
264 }
265 #[cfg(feature = "metrics")]
266 ctx.emit_metrics("aggregate");
267 Ok(())
268 }
269
270 #[inline]
272 async fn before_query(_query: &Query) -> Result<(), Error> {
273 Ok(())
274 }
275
276 #[inline]
278 async fn after_query(ctx: &QueryContext) -> Result<(), Error> {
279 if !ctx.is_success() {
280 ctx.record_error("fail to select the models from the table");
281 }
282 #[cfg(feature = "metrics")]
283 ctx.emit_metrics("query");
284 Ok(())
285 }
286
287 #[inline]
289 async fn before_mutation(_query: &Query, _mutation: &mut Mutation) -> Result<(), Error> {
290 Ok(())
291 }
292
293 #[inline]
295 async fn after_mutation(ctx: &QueryContext) -> Result<(), Error> {
296 if !ctx.is_success() {
297 ctx.record_error("fail to update the models in the table");
298 }
299 #[cfg(feature = "metrics")]
300 ctx.emit_metrics("mutation");
301 Ok(())
302 }
303
304 #[inline]
306 async fn before_list(
307 _query: &mut Query,
308 _extension: Option<&Self::Extension>,
309 ) -> Result<(), Error> {
310 Ok(())
311 }
312
313 #[inline]
315 async fn before_batch_delete(
316 _query: &mut Query,
317 _extension: Option<&Self::Extension>,
318 ) -> Result<(), Error> {
319 Ok(())
320 }
321
322 #[inline]
324 async fn after_populate(_model: &mut Map) -> Result<(), Error> {
325 Ok(())
326 }
327
328 #[inline]
330 async fn after_decode(_model: &mut Map) -> Result<(), Error> {
331 Ok(())
332 }
333
334 #[inline]
336 async fn before_respond(
337 _model: &mut Map,
338 _extension: Option<&Self::Extension>,
339 ) -> Result<(), Error> {
340 Ok(())
341 }
342
343 #[inline]
345 async fn before_mock() -> Result<Map, Error> {
346 Ok(Map::new())
347 }
348
349 #[inline]
351 async fn after_mock(&mut self) -> Result<(), Error> {
352 Ok(())
353 }
354}