feat(server): integrate AppState, ModuleRegistry, health check, and graceful shutdown

- Add AppState with DB, Config, EventBus, ModuleRegistry via Axum State
- ModuleRegistry now uses Arc for Clone support, builder-pattern register()
- Add /api/v1/health endpoint returning status, version, registered modules
- Add graceful shutdown on CTRL+C / SIGTERM
- erp-common utils: ID generation, timestamp helpers, code generator with tests
- Config structs now derive Clone for state sharing
- Update wiki to reflect Phase 1 completion
This commit is contained in:
iven
2026-04-11 01:19:30 +08:00
parent 5901ee82f0
commit 810eef769f
9 changed files with 216 additions and 30 deletions

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use axum::Router;
use uuid::Uuid;
@@ -38,19 +40,25 @@ pub trait ErpModule: Send + Sync {
}
}
/// 模块注册器
/// 模块注册器 — 用 Arc 包装使其可 Clone用于 Axum State
#[derive(Clone, Default)]
pub struct ModuleRegistry {
modules: Vec<Box<dyn ErpModule>>,
modules: Arc<Vec<Arc<dyn ErpModule>>>,
}
impl ModuleRegistry {
pub fn new() -> Self {
Self { modules: vec![] }
Self {
modules: Arc::new(vec![]),
}
}
pub fn register(&mut self, module: Box<dyn ErpModule>) {
pub fn register(mut self, module: impl ErpModule + 'static) -> Self {
tracing::info!(module = module.name(), version = module.version(), "Module registered");
self.modules.push(module);
let mut modules = (*self.modules).clone();
modules.push(Arc::new(module));
self.modules = Arc::new(modules);
self
}
pub fn build_router(&self, base: Router) -> Router {
@@ -60,12 +68,12 @@ impl ModuleRegistry {
}
pub fn register_handlers(&self, bus: &EventBus) {
for module in &self.modules {
for module in self.modules.iter() {
module.register_event_handlers(bus);
}
}
pub fn modules(&self) -> &[Box<dyn ErpModule>] {
pub fn modules(&self) -> &[Arc<dyn ErpModule>] {
&self.modules
}
}