1use crate::event_error::EventError;
2use crate::events::ModelObserver;
3use crate::observers::ObserverManager;
4
5pub struct ModelLifecycle {
6 observer_manager: ObserverManager,
7}
8
9impl ModelLifecycle {
10 pub fn new() -> Self {
11 Self {
12 observer_manager: ObserverManager::new(),
13 }
14 }
15
16 pub fn register_observer<T: 'static>(&mut self, observer: Box<dyn ModelObserver<T>>) {
17 self.observer_manager.register_for_model(observer);
18 }
19
20 pub fn register_global_observer<T: 'static>(&mut self, observer: Box<dyn ModelObserver<T>>) {
21 self.observer_manager.register_global(observer);
22 }
23
24 pub async fn trigger_create_flow<T: 'static>(&self, model: &mut T) -> Result<(), EventError> {
25 if let Some(registry) = self.observer_manager.get_registry_for::<T>() {
26 registry.trigger_creating(model).await?;
28 registry.trigger_saving(model).await?;
29 registry.trigger_saved(model).await?;
30 registry.trigger_created(model).await?;
31 }
32 Ok(())
33 }
34
35 pub async fn trigger_update_flow<T: 'static>(
36 &self,
37 model: &mut T,
38 original: &T,
39 ) -> Result<(), EventError> {
40 if let Some(registry) = self.observer_manager.get_registry_for::<T>() {
41 registry.trigger_updating(model, original).await?;
43 registry.trigger_saving(model).await?;
44 registry.trigger_saved(model).await?;
45 registry.trigger_updated(model, original).await?;
46 }
47 Ok(())
48 }
49
50 pub async fn trigger_delete_flow<T: 'static>(&self, model: &T) -> Result<(), EventError> {
51 if let Some(registry) = self.observer_manager.get_registry_for::<T>() {
52 registry.trigger_deleting(model).await?;
54 registry.trigger_deleted(model).await?;
55 }
56 Ok(())
57 }
58
59 pub fn has_observers_for<T: 'static>(&self) -> bool {
60 self.observer_manager.has_observers_for::<T>()
61 }
62}
63
64impl Default for ModelLifecycle {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use async_trait::async_trait;
74 use std::sync::{Arc, Mutex};
75
76 #[derive(Debug, Clone, PartialEq)]
77 struct TestUser {
78 id: i64,
79 name: String,
80 email: String,
81 }
82
83 impl Default for TestUser {
84 fn default() -> Self {
85 Self {
86 id: 1,
87 name: "Test User".to_string(),
88 email: "test@example.com".to_string(),
89 }
90 }
91 }
92
93 #[derive(Debug, Clone)]
94 struct LifecycleTracker {
95 events: Arc<Mutex<Vec<String>>>,
96 }
97
98 impl LifecycleTracker {
99 fn new() -> Self {
100 Self {
101 events: Arc::new(Mutex::new(Vec::new())),
102 }
103 }
104
105 fn track(&self, event: &str) {
106 self.events.lock().unwrap().push(event.to_string());
107 }
108
109 fn get_events(&self) -> Vec<String> {
110 self.events.lock().unwrap().clone()
111 }
112
113 #[allow(dead_code)]
114 fn clear(&self) {
115 self.events.lock().unwrap().clear();
116 }
117 }
118
119 #[derive(Clone)]
120 struct LifecycleObserver {
121 tracker: LifecycleTracker,
122 }
123
124 impl LifecycleObserver {
125 fn new(tracker: LifecycleTracker) -> Self {
126 Self { tracker }
127 }
128 }
129
130 #[async_trait]
131 impl ModelObserver<TestUser> for LifecycleObserver {
132 async fn creating(&self, model: &mut TestUser) -> Result<(), EventError> {
133 self.tracker.track(&format!("creating: {}", model.name));
134 model.email = model.email.to_lowercase();
136 Ok(())
137 }
138
139 async fn created(&self, model: &TestUser) -> Result<(), EventError> {
140 self.tracker.track(&format!("created: {}", model.name));
141 Ok(())
142 }
143
144 async fn updating(
145 &self,
146 model: &mut TestUser,
147 original: &TestUser,
148 ) -> Result<(), EventError> {
149 self.tracker
150 .track(&format!("updating: {} -> {}", original.name, model.name));
151 Ok(())
152 }
153
154 async fn updated(&self, model: &TestUser, original: &TestUser) -> Result<(), EventError> {
155 self.tracker
156 .track(&format!("updated: {} -> {}", original.name, model.name));
157 Ok(())
158 }
159
160 async fn saving(&self, model: &mut TestUser) -> Result<(), EventError> {
161 self.tracker.track(&format!("saving: {}", model.name));
162 Ok(())
163 }
164
165 async fn saved(&self, model: &TestUser) -> Result<(), EventError> {
166 self.tracker.track(&format!("saved: {}", model.name));
167 Ok(())
168 }
169
170 async fn deleting(&self, model: &TestUser) -> Result<(), EventError> {
171 self.tracker.track(&format!("deleting: {}", model.name));
172 Ok(())
173 }
174
175 async fn deleted(&self, model: &TestUser) -> Result<(), EventError> {
176 self.tracker.track(&format!("deleted: {}", model.name));
177 Ok(())
178 }
179 }
180
181 #[tokio::test]
182 async fn test_model_lifecycle_create_flow() {
183 let tracker = LifecycleTracker::new();
184 let observer = LifecycleObserver::new(tracker.clone());
185
186 let mut lifecycle = ModelLifecycle::new();
187 lifecycle.register_observer::<TestUser>(Box::new(observer));
188
189 let mut user = TestUser {
190 name: "John Doe".to_string(),
191 email: "JOHN@EXAMPLE.COM".to_string(),
192 ..Default::default()
193 };
194
195 let result = lifecycle.trigger_create_flow(&mut user).await;
197 assert!(result.is_ok());
198
199 let events = tracker.get_events();
200 assert_eq!(events.len(), 4);
201 assert_eq!(events[0], "creating: John Doe");
202 assert_eq!(events[1], "saving: John Doe");
203 assert_eq!(events[2], "saved: John Doe");
204 assert_eq!(events[3], "created: John Doe");
205
206 assert_eq!(user.email, "john@example.com");
208 }
209
210 #[tokio::test]
211 async fn test_model_lifecycle_update_flow() {
212 let tracker = LifecycleTracker::new();
213 let observer = LifecycleObserver::new(tracker.clone());
214
215 let mut lifecycle = ModelLifecycle::new();
216 lifecycle.register_observer::<TestUser>(Box::new(observer));
217
218 let original = TestUser::default();
219 let mut updated = TestUser {
220 name: "Updated User".to_string(),
221 ..original.clone()
222 };
223
224 let result = lifecycle.trigger_update_flow(&mut updated, &original).await;
226 assert!(result.is_ok());
227
228 let events = tracker.get_events();
229 assert_eq!(events.len(), 4);
230 assert_eq!(events[0], "updating: Test User -> Updated User");
231 assert_eq!(events[1], "saving: Updated User");
232 assert_eq!(events[2], "saved: Updated User");
233 assert_eq!(events[3], "updated: Test User -> Updated User");
234 }
235
236 #[tokio::test]
237 async fn test_model_lifecycle_delete_flow() {
238 let tracker = LifecycleTracker::new();
239 let observer = LifecycleObserver::new(tracker.clone());
240
241 let mut lifecycle = ModelLifecycle::new();
242 lifecycle.register_observer::<TestUser>(Box::new(observer));
243
244 let user = TestUser::default();
245
246 let result = lifecycle.trigger_delete_flow(&user).await;
248 assert!(result.is_ok());
249
250 let events = tracker.get_events();
251 assert_eq!(events.len(), 2);
252 assert_eq!(events[0], "deleting: Test User");
253 assert_eq!(events[1], "deleted: Test User");
254 }
255
256 #[tokio::test]
257 async fn test_model_lifecycle_error_stops_flow() {
258 struct FailingObserver;
259
260 #[async_trait]
261 impl ModelObserver<TestUser> for FailingObserver {
262 async fn creating(&self, _model: &mut TestUser) -> Result<(), EventError> {
263 Err(EventError::validation("Creation not allowed"))
264 }
265 }
266
267 let mut lifecycle = ModelLifecycle::new();
268 lifecycle.register_observer::<TestUser>(Box::new(FailingObserver));
269
270 let mut user = TestUser::default();
271
272 let result = lifecycle.trigger_create_flow(&mut user).await;
273 assert!(result.is_err());
274
275 match result.unwrap_err() {
276 EventError::Validation { message, .. } => {
277 assert_eq!(message, "Creation not allowed");
278 }
279 _ => panic!("Expected validation error"),
280 }
281 }
282
283 #[tokio::test]
284 async fn test_model_lifecycle_multiple_observers() {
285 let tracker1 = LifecycleTracker::new();
286 let tracker2 = LifecycleTracker::new();
287
288 let observer1 = LifecycleObserver::new(tracker1.clone());
289 let observer2 = LifecycleObserver::new(tracker2.clone());
290
291 let mut lifecycle = ModelLifecycle::new();
292 lifecycle.register_observer::<TestUser>(Box::new(observer1));
293 lifecycle.register_observer::<TestUser>(Box::new(observer2));
294
295 let mut user = TestUser::default();
296 let result = lifecycle.trigger_create_flow(&mut user).await;
297 assert!(result.is_ok());
298
299 let events1 = tracker1.get_events();
301 let events2 = tracker2.get_events();
302
303 assert_eq!(events1.len(), 4);
304 assert_eq!(events2.len(), 4);
305
306 assert_eq!(events1[0], "creating: Test User");
308 assert_eq!(events2[0], "creating: Test User");
309 }
310
311 #[tokio::test]
312 async fn test_model_lifecycle_observer_modification_persists() {
313 struct NormalizingObserver;
314
315 #[async_trait]
316 impl ModelObserver<TestUser> for NormalizingObserver {
317 async fn creating(&self, model: &mut TestUser) -> Result<(), EventError> {
318 model.name = model.name.to_uppercase();
319 model.email = model.email.to_lowercase();
320 Ok(())
321 }
322 }
323
324 let mut lifecycle = ModelLifecycle::new();
325 lifecycle.register_observer::<TestUser>(Box::new(NormalizingObserver));
326
327 let mut user = TestUser {
328 name: "john doe".to_string(),
329 email: "JOHN@EXAMPLE.COM".to_string(),
330 ..Default::default()
331 };
332
333 let result = lifecycle.trigger_create_flow(&mut user).await;
334 assert!(result.is_ok());
335
336 assert_eq!(user.name, "JOHN DOE");
338 assert_eq!(user.email, "john@example.com");
339 }
340
341 #[tokio::test]
342 async fn test_model_lifecycle_event_propagation_control() {
343 struct PropagationStoppingObserver;
344
345 #[async_trait]
346 impl ModelObserver<TestUser> for PropagationStoppingObserver {
347 async fn creating(&self, _model: &mut TestUser) -> Result<(), EventError> {
348 Err(EventError::propagation_stopped("User decided to cancel"))
349 }
350 }
351
352 let mut lifecycle = ModelLifecycle::new();
353 lifecycle.register_observer::<TestUser>(Box::new(PropagationStoppingObserver));
354
355 let mut user = TestUser::default();
356 let result = lifecycle.trigger_create_flow(&mut user).await;
357
358 assert!(result.is_err());
359 match result.unwrap_err() {
360 EventError::PropagationStopped { reason, .. } => {
361 assert_eq!(reason, "User decided to cancel");
362 }
363 _ => panic!("Expected propagation stopped error"),
364 }
365 }
366}