dmsc/core/lifecycle.rs
1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of DMSC.
4//! The DMSC project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//! http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18#![allow(non_snake_case)]
19
20//! # Lifecycle Observer
21//!
22//! This module provides a lifecycle observer that logs all hook events in the DMSC application.
23//! It implements the `ServiceModule` trait and registers handlers for all hook kinds to provide
24//! comprehensive lifecycle logging.
25//!
26//! ## Key Components
27//!
28//! - **DMSCLifecycleObserver**: Service module that logs all hook events
29//!
30//! ## Design Principles
31//!
32//! 1. **Comprehensive Logging**: Logs all hook events with detailed information
33//! 2. **Non-Intrusive**: Operates by listening to hook events without modifying core functionality
34//! 3. **Non-Critical**: Can fail without causing the entire system to fail
35//! 4. **Detailed Context**: Provides module, phase, and kind information for each event
36
37use crate::core::{DMSCResult, DMSCServiceContext, ServiceModule};
38use crate::hooks::{DMSCHookBus, DMSCHookEvent, DMSCHookKind};
39
40/// Lifecycle observer module for DMSC.
41///
42/// This module logs all hook events in the DMSC application, providing comprehensive
43/// visibility into the application lifecycle.
44#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
45pub struct DMSCLifecycleObserver;
46
47impl Default for DMSCLifecycleObserver {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl DMSCLifecycleObserver {
54 /// Creates a new instance of the lifecycle observer.
55 ///
56 /// Returns a new `DMSCLifecycleObserver` instance.
57 pub fn new() -> Self {
58 DMSCLifecycleObserver
59 }
60}
61
62impl ServiceModule for DMSCLifecycleObserver {
63 /// Returns the name of the lifecycle observer module.
64 ///
65 /// This name is used for identification, logging, and dependency resolution.
66 fn name(&self) -> &str {
67 "DMSC.LifecycleObserver"
68 }
69
70 /// Indicates if the lifecycle observer is critical to the operation of the system.
71 ///
72 /// The lifecycle observer is non-critical, meaning it can fail without causing the entire
73 /// system to fail.
74 fn is_critical(&self) -> bool {
75 false
76 }
77
78 /// Initializes the lifecycle observer.
79 ///
80 /// This method registers handlers for all hook kinds to log lifecycle events.
81 /// Each handler logs detailed information about the event, including:
82 /// - Hook kind
83 /// - Module name (if applicable)
84 /// - Module phase (if applicable)
85 ///
86 /// # Parameters
87 ///
88 /// - `ctx`: The service context containing the hook bus
89 ///
90 /// # Returns
91 ///
92 /// A `DMSCResult` indicating success or failure
93 fn init(&mut self, ctx: &mut DMSCServiceContext) -> DMSCResult<()> {
94 let hooks: &mut DMSCHookBus = ctx.hooks_mut();
95 let all_kinds = [
96 DMSCHookKind::Startup,
97 DMSCHookKind::Shutdown,
98 DMSCHookKind::BeforeModulesInit,
99 DMSCHookKind::AfterModulesInit,
100 DMSCHookKind::BeforeModulesStart,
101 DMSCHookKind::AfterModulesStart,
102 DMSCHookKind::BeforeModulesShutdown,
103 DMSCHookKind::AfterModulesShutdown,
104 DMSCHookKind::ConfigReload,
105 ];
106
107 for &kind in &all_kinds {
108 let kind_str = match kind {
109 DMSCHookKind::Startup => "Startup",
110 DMSCHookKind::Shutdown => "Shutdown",
111 DMSCHookKind::BeforeModulesInit => "BeforeModulesInit",
112 DMSCHookKind::AfterModulesInit => "AfterModulesInit",
113 DMSCHookKind::BeforeModulesStart => "BeforeModulesStart",
114 DMSCHookKind::AfterModulesStart => "AfterModulesStart",
115 DMSCHookKind::BeforeModulesShutdown => "BeforeModulesShutdown",
116 DMSCHookKind::AfterModulesShutdown => "AfterModulesShutdown",
117 DMSCHookKind::ConfigReload => "ConfigReload",
118 };
119 let handler_name = format!("dms.lifecycle.{}", kind_str.to_lowercase());
120
121 hooks.register(kind, handler_name, move |_ctx, event: &DMSCHookEvent| {
122 let logger = _ctx.logger();
123 let module = event.module.as_deref().unwrap_or("-");
124 let phase = event.phase.map(|p| p.as_str()).unwrap_or("-");
125 let message = format!("kind={} module={} phase={}", kind_str, module, phase);
126 let _ = logger.info("DMSC.Lifecycle", message);
127 Ok(())
128 });
129 }
130
131 Ok(())
132 }
133}
134
135#[cfg(feature = "pyo3")]
136#[pyo3::prelude::pymethods]
137impl DMSCLifecycleObserver {
138 #[new]
139 fn new_py() -> Self {
140 Self::new()
141 }
142
143 fn name(&self) -> String {
144 "DMSC.LifecycleObserver".to_string()
145 }
146
147 fn is_critical(&self) -> bool {
148 false
149 }
150
151 fn __repr__(&self) -> String {
152 "DMSCLifecycleObserver".to_string()
153 }
154}