Skip to main content

tx_di_core/
lifecycle.rs

1//! 生命周期管理 — BuildContext 和 App
2//!
3//! BuildContext 负责构建阶段:加载配置 → 拓扑排序 → 构建组件 → inner_init
4//! App 负责运行阶段:init → async_init → async_run → shutdown
5
6use std::any::{Any, TypeId};
7use std::collections::HashMap;
8use std::path::PathBuf;
9use std::sync::{Arc, LazyLock};
10
11use dashmap::DashMap;
12use tokio::signal;
13use tokio::sync::RwLock;
14use tokio::task::JoinHandle;
15use tokio::time::Instant;
16use tokio_util::sync::CancellationToken;
17use tracing::{debug, info};
18
19use crate::component::Component;
20use crate::config::AppAllConfig;
21use crate::registry::{ComponentMeta, COMPONENT_REGISTRY};
22use crate::scope::Scope;
23use crate::store::{CompRef, Store, TraitImplEntry};
24use crate::topology::{all_metas, topo_sort};
25use crate::RIE;
26
27/// 内部上下文类型别名
28pub type InnerContext = DashMap<TypeId, CompRef>;
29
30/// 全局系统配置
31static SYS_CONFIG: LazyLock<DashMap<String, String>> = LazyLock::new(DashMap::new);
32
33/// 获取全局配置
34pub fn get_sys_config(key: &str) -> Option<String> {
35    SYS_CONFIG.get(key).map(|v| v.value().clone())
36}
37
38/// 设置全局配置
39pub fn set_sys_config(key: &str, value: String) {
40    SYS_CONFIG.insert(key.to_string(), value);
41}
42
43/// 配置路径 key
44pub const CONFIG_PATH: &str = "config_path";
45
46// ── BuildContext ──────────────────────────────────────────────────────────
47
48/// 构建上下文 — 负责组件注册和初始化
49pub struct BuildContext {
50    store: Store,
51    metas: Vec<&'static ComponentMeta>,
52}
53
54impl BuildContext {
55    /// 创建一个新的 BuildContext(仅供内部使用 DashMap 的场景)
56    pub fn inner_new(ctx: InnerContext) -> Self {
57        BuildContext {
58            store: Store::from_dashmap(ctx),
59            metas: vec![],
60        }
61    }
62
63    /// 创建一个新的 BuildContext
64    ///
65    /// # 参数
66    ///
67    /// * `config_path` - 可选的配置文件路径
68    #[inline]
69    pub fn new<P: Into<PathBuf>>(config_path: Option<P>) -> Self {
70        let mut ctx = Self {
71            store: Store::new(),
72            metas: vec![],
73        };
74
75        // 加载配置文件并放入 store
76        let app_configs = AppAllConfig::new(config_path);
77        ctx.store.insert_cached(app_configs);
78
79        // 自动扫描并注册所有组件
80        ctx.auto_register_all();
81
82        ctx
83    }
84
85    /// 自动注册所有通过 `#[derive(Component)]` 标记的组件
86    fn auto_register_all(&mut self) {
87        // 1. 填充 trait_impls(每个 Store 拥有独立的 trait 映射,无全局污染)
88        for meta in COMPONENT_REGISTRY.iter() {
89            if !meta.trait_impls.is_empty() {
90                for trait_fn in meta.impl_traits {
91                    let trait_tid = trait_fn();
92                    self.store
93                        .trait_impls
94                        .entry(trait_tid)
95                        .or_default()
96                        .extend(meta.trait_impls.to_vec());
97                    debug!("组件 '{}' 实现了 trait {:?}", meta.name, trait_tid);
98                }
99            }
100        }
101
102        // 2. 拓扑排序
103        let metas: Vec<&'static ComponentMeta> = COMPONENT_REGISTRY.iter().collect();
104        let sorted_ids = topo_sort(&metas, &self.store.trait_impls).unwrap_or_else(|e| {
105            panic!("{}", e);
106        });
107
108        // 3. 按拓扑顺序注册工厂
109        for tid in &sorted_ids {
110            if let Some(meta) = metas.iter().find(|m| (m.type_id)() == *tid) {
111                self.register_factory(meta);
112                self.metas.push(meta);
113            }
114        }
115    }
116
117    /// 注册组件工厂
118    ///
119    /// - Singleton:立即调用工厂并缓存为 `CompRef::Cached`
120    /// - Prototype:存为 `CompRef::Factory` 闭包
121    fn register_factory(&mut self, meta: &ComponentMeta) {
122        let type_id = (meta.type_id)();
123        let scope = meta.scope;
124        let factory = meta.factory;
125
126        match scope {
127            Scope::Singleton => {
128                let instance = factory(&self.store);
129                let arc: Arc<dyn Any + Send + Sync> = Arc::from(instance);
130                self.store.inner().insert(type_id, CompRef::Cached(arc));
131            }
132            Scope::Prototype => {
133                let closure =
134                    move |store: &Store| -> Arc<dyn Any + Send + Sync> {
135                        let boxed = factory(store);
136                        Arc::from(boxed)
137                    };
138                self.store
139                    .inner()
140                    .insert(type_id, CompRef::Factory(Arc::new(closure)));
141            }
142        }
143    }
144
145    // ── 注入入口 ─────────────────────────────────────────────────────────
146
147    /// 注入组件实例
148    pub fn inject<T: Component>(&self) -> Arc<T> {
149        self.store.inject_or_panic::<T>()
150    }
151
152    /// 尝试注入,失败返回 None
153    pub fn try_inject<T: Component>(&self) -> Option<Arc<T>> {
154        self.store.try_inject::<T>()
155    }
156
157    /// 获取 Store 引用
158    pub fn store(&self) -> &Store {
159        &self.store
160    }
161
162    // ── 调试辅助 ────────────────────────────────────────────────────────
163
164    /// 已注册组件数量
165    #[inline]
166    pub fn len(&self) -> usize {
167        self.store.len()
168    }
169
170    /// 是否为空
171    #[inline]
172    pub fn is_empty(&self) -> bool {
173        self.store.is_empty()
174    }
175
176    /// 打印所有已注册的组件(调试用)
177    pub fn debug_registry() -> RIE<()> {
178        let metas = all_metas();
179        let id_to_idx: HashMap<TypeId, (usize, &str)> = metas
180            .iter()
181            .enumerate()
182            .map(|(i, m)| ((m.type_id)(), (i, m.name)))
183            .collect();
184
185        // 构建临时 trait_impls 用于拓扑排序(无 Store 环境)
186        let temp_trait_impls: DashMap<TypeId, Vec<TraitImplEntry>> = DashMap::new();
187        for meta in COMPONENT_REGISTRY.iter() {
188            if !meta.trait_impls.is_empty() {
189                for trait_fn in meta.impl_traits {
190                    let trait_tid = trait_fn();
191                    temp_trait_impls
192                        .entry(trait_tid)
193                        .or_default()
194                        .extend(meta.trait_impls.to_vec());
195                }
196            }
197        }
198
199        let ans = topo_sort(&metas, &temp_trait_impls).map_err(|e| {
200            crate::AppError::Internal(anyhow::anyhow!("{}", e))
201        })?;
202
203        debug!("组件注册表(拓扑排序后):");
204        debug!("{:20} {:10} deps", "name", "scope");
205        for tid in ans.iter() {
206            let meta = metas[id_to_idx
207                .get(tid)
208                .ok_or_else(|| crate::AppError::Internal(anyhow::anyhow!("RegistryError")))?
209                .0];
210            let dep_names: Vec<&str> = meta
211                .dep_type_ids
212                .iter()
213                .map(|dep_fn| {
214                    COMPONENT_REGISTRY
215                        .iter()
216                        .find(|m| (m.type_id)() == dep_fn())
217                        .map(|m| m.name)
218                        .unwrap_or("unknown")
219                })
220                .collect();
221            debug!(
222                "{:20} {:10} [{}]",
223                meta.name,
224                format!("{:?}", meta.scope),
225                dep_names.join(", ")
226            )
227        }
228        Ok(())
229    }
230
231    // ── 构建 App ────────────────────────────────────────────────────────
232
233    /// 构建 App 实例,将 store 转移到 App
234    pub fn build(mut self) -> RIE<App> {
235        let shutdown_token = CancellationToken::new();
236        let store = std::mem::replace(&mut self.store, Store::new());
237        let metas = std::mem::take(&mut self.metas);
238        Ok(App {
239            store,
240            metas,
241            shutdown_token,
242            task_handle: RwLock::new(None),
243        })
244    }
245
246    /// 构建 App 并运行
247    pub async fn build_and_run(self) -> RIE<()> {
248        let app = self.build()?;
249        let arc_app = Arc::new(app);
250        App::run(arc_app.clone(), arc_app.shutdown_token.clone()).await
251    }
252}
253
254impl Default for BuildContext {
255    fn default() -> Self {
256        Self::new::<PathBuf>(None)
257    }
258}
259
260// ── App ───────────────────────────────────────────────────────────────────
261
262/// 运行时 App — 持有所有已初始化的组件
263pub struct App {
264    pub store: Store,
265    pub metas: Vec<&'static ComponentMeta>,
266    pub shutdown_token: CancellationToken,
267    pub task_handle: RwLock<Option<JoinHandle<()>>>,
268}
269
270impl App {
271    /// 获取组件实例
272    pub fn inject<T: Component>(&self) -> Arc<T> {
273        self.store.inject_or_panic::<T>()
274    }
275
276    /// 尝试获取组件,失败返回 None
277    pub fn try_inject<T: Component>(&self) -> Option<Arc<T>> {
278        self.store.try_inject::<T>()
279    }
280
281    /// 获取组件总数
282    #[inline]
283    pub fn len(&self) -> usize {
284        self.store.len()
285    }
286
287    /// 检查 App 是否为空
288    #[inline]
289    pub fn is_empty(&self) -> bool {
290        self.store.is_empty()
291    }
292
293    /// 获取 Store 引用
294    pub fn store(&self) -> &Store {
295        &self.store
296    }
297
298    // ── 生命周期执行 ─────────────────────────────────────────────────────
299
300    /// 同步初始化阶段:按已排序顺序(拓扑序 + init_sort)调用所有组件的 init()
301    fn init(app: &Arc<App>) -> RIE<()> {
302        // App.metas 已在 BuildContext::auto_register_all 中按 topo_sort(init_sort) 排序,
303        // 同时满足依赖关系和 init_sort 优先级,无需重复排序
304        for meta in &app.metas {
305            debug!("[di] init: {}", meta.name);
306            (meta.init_fn)(app)?;
307        }
308        Ok(())
309    }
310
311    /// 异步初始化阶段:按已排序顺序(拓扑序 + init_sort)调用所有组件的 async_init()
312    async fn async_init(app: &Arc<App>) -> RIE<()> {
313        // 同 init(),复用 BuildContext 已排好的顺序
314        for meta in &app.metas {
315            debug!("[di] async_init: {}", meta.name);
316            (meta.async_init_fn)(app).await?;
317        }
318        Ok(())
319    }
320
321    /// 并行运行所有组件的 async_run()
322    async fn comp_run(app: Arc<App>, token: CancellationToken) -> RIE<()> {
323        let mut handles = Vec::new();
324
325        // 先收集所有 meta 引用,避免借用 app.metas
326        let metas: Vec<&'static ComponentMeta> = app.metas.clone();
327        for meta in metas {
328            let app_clone = app.clone();
329            let token_clone = token.clone();
330            let name = meta.name;
331            debug!("[di] async_run spawn: {}", name);
332
333            let handle = tokio::spawn(async move {
334                if let Err(e) = (meta.async_run_fn)(&app_clone, token_clone).await {
335                    tracing::error!("[di] 组件 '{}' async_run 失败: {:?}", name, e);
336                }
337            });
338            handles.push(handle);
339        }
340        // 等待所有后台任务完成(或被 cancel)
341        for handle in handles {
342            let _ = handle.await;
343        }
344        Ok(())
345    }
346
347    /// 运行 App(init → async_init → async_run)
348    async fn run(app: Arc<App>, token: CancellationToken) -> RIE<()> {
349        App::init(&app)?;
350        App::async_init(&app).await?;
351        App::comp_run(app, token).await?;
352        Ok(())
353    }
354
355    /// 异步运行 App,返回 Arc<App>
356    ///
357    /// 初始化阶段(`init` + `async_init`)会在返回 `Arc<App>` **之前**同步完成,
358    /// 以确保组件完全就绪(如 AOP 拦截链注册、跨组件协作初始化)后再交予调用方使用。
359    /// 仅长期运行的后台任务(`async_run`)放入独立 task 中持续运行,
360    /// 直到 `shutdown_token` 触发才退出。
361    pub async fn ins_run(self) -> RIE<Arc<App>> {
362        let app = Arc::new(App {
363            store: self.store,
364            metas: self.metas,
365            shutdown_token: self.shutdown_token,
366            task_handle: self.task_handle,
367        });
368
369        // 初始化阶段必须先完成,否则调用方立即访问组件时会因尚未就绪而失败
370        // (例如被 #[component(intercept(...))] 标记的组件其拦截链在 init 中注册)。
371        App::init(&app)?;
372        App::async_init(&app).await?;
373
374        // 仅长期后台任务(async_run)放入独立 task 运行,直到 token 触发退出
375        let app_clone = app.clone();
376        let app_handler = tokio::spawn(async move {
377            if let Err(e) = App::comp_run(app_clone.clone(), app_clone.shutdown_token.clone()).await {
378                tracing::error!("[di] App 运行失败: {:?},将执行 shutdown", e);
379                app_clone.shutdown().await;
380            }
381        });
382
383        {
384            let mut guard = app.task_handle.write().await;
385            *guard = Some(app_handler);
386        }
387
388        Ok(app)
389    }
390
391    /// 优雅关闭所有组件
392    pub async fn shutdown(&self) {
393        let metas: Vec<&ComponentMeta> = self.metas.clone();
394        // 逆序关闭(后注册的先关闭)
395        for meta in metas.iter().rev() {
396            debug!("[di] shutdown: {}", meta.name);
397            (meta.shutdown_fn)(&self.store);
398        }
399    }
400
401    /// 等待退出信号并优雅关闭
402    pub async fn waiting_exit(&self) {
403        App::wait_for_exit_signal().await;
404        let start = Instant::now();
405        info!("正在等待退出...");
406        self.shutdown_token.cancel();
407
408        if let Some(handle) = self.task_handle.write().await.take() {
409            match tokio::time::timeout(std::time::Duration::from_secs(5), handle).await {
410                Ok(Ok(())) => {
411                    info!("后台任务已正常关闭");
412                }
413                Ok(Err(e)) => {
414                    tracing::error!("后台任务退出时发生错误: {:?}", e);
415                }
416                Err(_) => {
417                    tracing::warn!("后台任务关闭超时(5秒),强制退出");
418                }
419            }
420        }
421
422        // 优雅关闭所有组件
423        self.shutdown().await;
424
425        info!("app 已退出,耗时: {:?}", start.elapsed());
426        tokio::time::sleep(std::time::Duration::from_millis(200)).await;
427    }
428
429    /// 跨平台等待退出信号
430    async fn wait_for_exit_signal() {
431        #[cfg(unix)]
432        {
433            let mut sigterm = signal::unix::signal(signal::unix::SignalKind::terminate())
434                .expect("无法注册 SIGTERM 处理器");
435            let mut sighup = signal::unix::signal(signal::unix::SignalKind::hangup())
436                .expect("无法注册 SIGHUP 处理器");
437            tokio::select! {
438                _ = signal::ctrl_c() => {},
439                _ = sigterm.recv() => {},
440                _ = sighup.recv() => {},
441            }
442        }
443        #[cfg(windows)]
444        {
445            use tokio::signal::windows;
446            let ctrl_c = signal::ctrl_c();
447            let mut ctrl_break = windows::ctrl_break().expect("无法注册 Ctrl+Break 处理器");
448            let mut ctrl_close = windows::ctrl_close().expect("无法注册 Ctrl+Close 处理器");
449            let mut ctrl_shutdown =
450                windows::ctrl_shutdown().expect("无法注册 Ctrl+Shutdown 处理器");
451            tokio::select! {
452                _ = ctrl_c => {},
453                _ = ctrl_break.recv() => {},
454                _ = ctrl_close.recv() => {},
455                _ = ctrl_shutdown.recv() => {},
456            }
457        }
458        #[cfg(all(not(unix), not(windows)))]
459        {
460            let _ = signal::ctrl_c().await;
461        }
462    }
463}