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}