Skip to main content

ri/core/
lifecycle.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri 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 Ri 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//! - **RiLifecycleObserver**: 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::{RiResult, RiServiceContext, ServiceModule};
38use crate::hooks::{RiHookBus, RiHookEvent, RiHookKind};
39
40/// Lifecycle observer module for Ri.
41/// 
42/// This module logs all hook events in the Ri application, providing comprehensive
43/// visibility into the application lifecycle.
44#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
45pub struct RiLifecycleObserver;
46
47impl Default for RiLifecycleObserver {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl RiLifecycleObserver {
54    /// Creates a new instance of the lifecycle observer.
55    /// 
56    /// Returns a new `RiLifecycleObserver` instance.
57    pub fn new() -> Self {
58        RiLifecycleObserver
59    }
60}
61
62impl ServiceModule for RiLifecycleObserver {
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        "Ri.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 `RiResult` indicating success or failure
93    fn init(&mut self, ctx: &mut RiServiceContext) -> RiResult<()> {
94        let hooks: &mut RiHookBus = ctx.hooks_mut();
95        let all_kinds = [
96            RiHookKind::Startup,
97            RiHookKind::Shutdown,
98            RiHookKind::BeforeModulesInit,
99            RiHookKind::AfterModulesInit,
100            RiHookKind::BeforeModulesStart,
101            RiHookKind::AfterModulesStart,
102            RiHookKind::BeforeModulesShutdown,
103            RiHookKind::AfterModulesShutdown,
104            RiHookKind::ConfigReload,
105        ];
106
107        for &kind in &all_kinds {
108            let kind_str = match kind {
109                RiHookKind::Startup => "Startup",
110                RiHookKind::Shutdown => "Shutdown",
111                RiHookKind::BeforeModulesInit => "BeforeModulesInit",
112                RiHookKind::AfterModulesInit => "AfterModulesInit",
113                RiHookKind::BeforeModulesStart => "BeforeModulesStart",
114                RiHookKind::AfterModulesStart => "AfterModulesStart",
115                RiHookKind::BeforeModulesShutdown => "BeforeModulesShutdown",
116                RiHookKind::AfterModulesShutdown => "AfterModulesShutdown",
117                RiHookKind::ConfigReload => "ConfigReload",
118            };
119            let handler_name = format!("dms.lifecycle.{}", kind_str.to_lowercase());
120            
121            hooks.register(kind, handler_name, move |_ctx, event: &RiHookEvent| {
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("Ri.Lifecycle", message);
127                Ok(())
128            });
129        }
130
131        Ok(())
132    }
133}
134
135#[cfg(feature = "pyo3")]
136#[pyo3::prelude::pymethods]
137impl RiLifecycleObserver {
138    #[new]
139    fn new_py() -> Self {
140        Self::new()
141    }
142
143    fn name(&self) -> String {
144        "Ri.LifecycleObserver".to_string()
145    }
146
147    fn is_critical(&self) -> bool {
148        false
149    }
150
151    fn __repr__(&self) -> String {
152        "RiLifecycleObserver".to_string()
153    }
154}