init: ShowenV2 项目骨架 — 数字生命窗口平台
- core/ 跨平台内核骨架 (Plugin trait, Message, ServiceManager, Config) - plugins/ 空桩 (video, http, ble, screen, wifi) - PROGRESS.md 进度跟踪, TEAM.md 团队档案 - cargo check 零 warning 通过 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
135
src/core/service_manager.rs
Normal file
135
src/core/service_manager.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
use crate::core::config::AppConfig;
|
||||
use crate::core::message::{Destination, Envelope, Message};
|
||||
use crate::core::plugin::{Plugin, PluginContext};
|
||||
use anyhow::Result;
|
||||
use std::sync::{mpsc, Arc};
|
||||
|
||||
/// 中央调度器:插件注册、生命周期管理、消息路由
|
||||
pub struct ServiceManager {
|
||||
plugins: Vec<Box<dyn Plugin>>,
|
||||
config: Arc<AppConfig>,
|
||||
tx: mpsc::Sender<Envelope>,
|
||||
rx: mpsc::Receiver<Envelope>,
|
||||
}
|
||||
|
||||
impl ServiceManager {
|
||||
pub fn new(config: AppConfig) -> Self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
Self {
|
||||
plugins: Vec::new(),
|
||||
config: Arc::new(config),
|
||||
tx,
|
||||
rx,
|
||||
}
|
||||
}
|
||||
|
||||
/// 注册插件
|
||||
pub fn register(&mut self, plugin: Box<dyn Plugin>) {
|
||||
println!("[ServiceManager] 注册插件: {}", plugin.id());
|
||||
self.plugins.push(plugin);
|
||||
}
|
||||
|
||||
/// 按注册顺序 init() + start() 所有插件
|
||||
pub fn start_all(&mut self) -> Result<()> {
|
||||
// init
|
||||
for plugin in &mut self.plugins {
|
||||
let ctx = PluginContext {
|
||||
tx: self.tx.clone(),
|
||||
config: Arc::clone(&self.config),
|
||||
};
|
||||
println!("[ServiceManager] 初始化插件: {}", plugin.id());
|
||||
plugin.init(ctx)?;
|
||||
}
|
||||
// start
|
||||
for plugin in &mut self.plugins {
|
||||
println!("[ServiceManager] 启动插件: {}", plugin.id());
|
||||
plugin.start()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 主消息循环(阻塞)
|
||||
pub fn run(&mut self) -> Result<()> {
|
||||
println!("[ServiceManager] 进入主消息循环");
|
||||
loop {
|
||||
let envelope = match self.rx.recv() {
|
||||
Ok(env) => env,
|
||||
Err(_) => {
|
||||
println!("[ServiceManager] 所有发送端已关闭,退出");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
match envelope.to {
|
||||
Destination::Plugin(id) => {
|
||||
if let Some(plugin) = self.plugins.iter_mut().find(|p| p.id() == id) {
|
||||
if let Err(e) = plugin.handle_message(envelope.message) {
|
||||
eprintln!("[ServiceManager] 插件 '{}' 处理消息失败: {}", id, e);
|
||||
}
|
||||
} else {
|
||||
eprintln!("[ServiceManager] 目标插件 '{}' 不存在", id);
|
||||
}
|
||||
}
|
||||
Destination::Broadcast => {
|
||||
let from = envelope.from;
|
||||
for plugin in &mut self.plugins {
|
||||
// 不回送给发送者
|
||||
if plugin.id() == from {
|
||||
continue;
|
||||
}
|
||||
// Broadcast 需要重建 Message(Message 不是 Clone)
|
||||
// 对于 Broadcast 我们跳过非 Shutdown 消息的深拷贝问题
|
||||
// 实际实现中 Shutdown 是最关键的广播消息
|
||||
}
|
||||
// 处理 Shutdown
|
||||
if matches!(envelope.message, Message::Shutdown) {
|
||||
println!("[ServiceManager] 收到 Shutdown 广播");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Destination::Manager => {
|
||||
self.handle_manager_message(envelope.message)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.stop_all()
|
||||
}
|
||||
|
||||
/// 逆序 stop() 所有插件
|
||||
pub fn stop_all(&mut self) -> Result<()> {
|
||||
println!("[ServiceManager] 停止所有插件");
|
||||
for plugin in self.plugins.iter_mut().rev() {
|
||||
println!("[ServiceManager] 停止插件: {}", plugin.id());
|
||||
if let Err(e) = plugin.stop() {
|
||||
eprintln!("[ServiceManager] 停止插件 '{}' 失败: {}", plugin.id(), e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 处理发给管理层自身的消息
|
||||
fn handle_manager_message(&mut self, msg: Message) -> Result<()> {
|
||||
match msg {
|
||||
Message::Shutdown => {
|
||||
println!("[ServiceManager] 收到 Shutdown 指令");
|
||||
// 通过返回 Err 来退出 run 循环不合适,用标志位
|
||||
// 实际上 run() 中已经 break 了
|
||||
}
|
||||
Message::ConfigReloadRequest => {
|
||||
println!("[ServiceManager] 收到配置重载请求");
|
||||
// TODO: 重载配置并广播 ConfigReloaded
|
||||
}
|
||||
Message::PluginReady(id) => {
|
||||
println!("[ServiceManager] 插件 '{}' 就绪", id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 获取发送通道的克隆(供外部使用)
|
||||
pub fn sender(&self) -> mpsc::Sender<Envelope> {
|
||||
self.tx.clone()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user