fix: 修复3个P0遗留 — AutoRollback回退/ConfigReloaded序列化/FfiString跨allocator

This commit is contained in:
showen
2026-03-13 05:15:04 +08:00
parent 1264b94e36
commit 6067c3f0a2
10 changed files with 393 additions and 57 deletions

View File

@@ -2,6 +2,7 @@ use crate::core::config::AppConfig;
use crate::core::message::{Destination, Envelope, Message};
use crate::core::plugin::{CapabilityTestResult, Plugin, PluginContext};
use crate::core::plugin_loader::ErrorPolicy;
use crate::core::version_manager::VersionManager;
use anyhow::{anyhow, Result};
use std::collections::{HashMap, HashSet};
use std::sync::{mpsc, Arc};
@@ -27,6 +28,8 @@ struct PluginState {
required_capabilities: Vec<String>,
/// 是否自动测试
auto_test: bool,
/// 是否需要在后续生命周期中执行回退
needs_rollback: bool,
}
impl PluginState {
@@ -42,6 +45,7 @@ impl PluginState {
capabilities: vec![],
required_capabilities: vec![],
auto_test: false, // 静态插件默认不自测
needs_rollback: false,
}
}
@@ -57,6 +61,7 @@ impl PluginState {
capabilities: vec![],
required_capabilities: vec![],
auto_test: true,
needs_rollback: false,
}
}
@@ -83,6 +88,7 @@ pub struct ServiceManager {
tx: mpsc::Sender<Envelope>,
rx: mpsc::Receiver<Envelope>,
running: bool,
version_manager: Option<VersionManager>,
}
impl ServiceManager {
@@ -94,9 +100,14 @@ impl ServiceManager {
tx,
rx,
running: false,
version_manager: None,
}
}
pub fn set_version_manager(&mut self, version_manager: VersionManager) {
self.version_manager = Some(version_manager);
}
/// 注册静态插件(编译时链接的插件)
pub fn register(&mut self, plugin: Box<dyn Plugin>) {
println!("[ServiceManager] 注册插件: {}", plugin.id());
@@ -351,10 +362,49 @@ impl ServiceManager {
enabled: s.enabled,
test_results: s.test_results.clone(),
capabilities: s.capabilities.clone(),
needs_rollback: s.needs_rollback,
})
.collect()
}
fn replace_dynamic_plugin_at_index(
&mut self,
idx: usize,
plugin_id: &str,
new_plugin: Box<dyn Plugin>,
error_policy: ErrorPolicy,
max_errors: u32,
required_capabilities: Vec<String>,
capabilities: Vec<String>,
auto_test: bool,
) -> Result<()> {
if !self.plugins[idx].is_dynamic {
return Err(anyhow!(
"plugin '{plugin_id}' is not dynamic and cannot be replaced"
));
}
let mut new_state = PluginState::new_dynamic(new_plugin, error_policy, max_errors);
new_state.required_capabilities = required_capabilities;
new_state.capabilities = capabilities;
new_state.auto_test = auto_test;
let ctx = PluginContext {
tx: self.tx.clone(),
config: Arc::clone(&self.config),
};
new_state.plugin.init(ctx)?;
new_state.plugin.start()?;
if self.plugins[idx].enabled {
let _ = self.plugins[idx].plugin.stop();
}
self.plugins[idx] = new_state;
println!("[ServiceManager] 插件 '{plugin_id}' 热替换成功");
Ok(())
}
/// 热替换动态插件stop 旧的 → 替换 → init → start 新的)
pub fn replace_dynamic_plugin(
&mut self,
@@ -374,22 +424,21 @@ impl ServiceManager {
"plugin '{plugin_id}' is not dynamic and cannot be replaced"
));
}
let mut new_state = PluginState::new_dynamic(new_plugin, error_policy, max_errors);
let ctx = PluginContext {
tx: self.tx.clone(),
config: Arc::clone(&self.config),
};
new_state.plugin.init(ctx)?;
new_state.plugin.start()?;
let required_capabilities = self.plugins[idx].required_capabilities.clone();
let capabilities = self.plugins[idx].capabilities.clone();
let auto_test = self.plugins[idx].auto_test;
if self.plugins[idx].enabled {
let _ = self.plugins[idx].plugin.stop();
}
self.plugins[idx] = new_state;
println!("[ServiceManager] 插件 '{plugin_id}' 热替换成功");
Ok(())
self.replace_dynamic_plugin_at_index(
idx,
plugin_id,
new_plugin,
error_policy,
max_errors,
required_capabilities,
capabilities,
auto_test,
)
}
/// 处理发给管理层自身的消息
@@ -424,7 +473,7 @@ impl ServiceManager {
let new_config = Arc::new(new_config);
self.config = Arc::clone(&new_config);
println!("[ServiceManager] 配置重载成功,广播 ConfigReloaded");
self.broadcast_message(Message::ConfigReloaded(new_config));
self.broadcast_message(Message::ConfigReloaded((*new_config).clone()));
}
Err(e) => {
eprintln!("[ServiceManager] 配置重载失败: {}", e);
@@ -588,28 +637,102 @@ impl ServiceManager {
/// 插件错误达到阈值时的处理
fn handle_error_threshold(&mut self, plugin_id: &str) {
let state = match self.plugins.iter_mut().find(|s| s.id() == plugin_id) {
Some(s) => s,
let idx = match self.plugins.iter().position(|s| s.id() == plugin_id) {
Some(idx) => idx,
None => return,
};
match state.error_policy {
match self.plugins[idx].error_policy.clone() {
ErrorPolicy::DisableAndLog => {
eprintln!(
"[ServiceManager] 插件 '{}' 错误次数达到阈值,已禁用",
plugin_id
);
let state = &mut self.plugins[idx];
let _ = state.plugin.stop();
state.enabled = false;
state.needs_rollback = false;
}
ErrorPolicy::AutoRollback => {
{
let state = &mut self.plugins[idx];
let _ = state.plugin.stop();
state.enabled = false;
state.needs_rollback = false;
}
eprintln!(
"[ServiceManager] 插件 '{}' 错误次数达到阈值,需要回退 (由外部 VersionManager 处理)",
"[ServiceManager] 插件 '{}' 错误次数达到阈值,尝试自动回退到稳定版本",
plugin_id
);
// 先禁用,等待外部 (main.rs / HTTP API) 调用 VersionManager 执行回退
let _ = state.plugin.stop();
state.enabled = false;
let rollback_result = {
let Some(version_manager) = self.version_manager.as_ref() else {
eprintln!(
"[ServiceManager] 插件 '{}' 未配置 VersionManager标记为待回退",
plugin_id
);
self.plugins[idx].needs_rollback = true;
return;
};
match version_manager.rollback(plugin_id) {
Ok(version) => match version_manager
.loader()
.load_plugin(plugin_id, Some(&version))
{
Ok((plugin, manifest)) => {
Ok((version, Box::new(plugin) as Box<dyn Plugin>, manifest))
}
Err(e) => Err((Some(version), e)),
},
Err(e) => Err((None, e)),
}
};
match rollback_result {
Ok((version, plugin, manifest)) => {
let max_errors = self.plugins[idx].max_errors;
match self.replace_dynamic_plugin_at_index(
idx,
plugin_id,
plugin,
manifest.error_policy,
max_errors,
manifest.required_capabilities,
manifest.capabilities,
manifest.auto_test,
) {
Ok(()) => {
println!(
"[ServiceManager] 插件 '{}' 已回退并重新加载稳定版本 {}",
plugin_id, version
);
}
Err(e) => {
eprintln!(
"[ServiceManager] 插件 '{}' 已切换到稳定版本 {},但热替换失败: {}",
plugin_id, version, e
);
self.plugins[idx].needs_rollback = true;
}
}
}
Err((Some(version), e)) => {
eprintln!(
"[ServiceManager] 插件 '{}' 已切换到稳定版本 {},但加载回退版本失败: {}",
plugin_id, version, e
);
self.plugins[idx].needs_rollback = true;
}
Err((None, e)) => {
eprintln!(
"[ServiceManager] 插件 '{}' 自动回退失败,标记为待回退: {}",
plugin_id, e
);
self.plugins[idx].needs_rollback = true;
}
}
}
}
}
@@ -632,4 +755,5 @@ pub struct PluginStateInfo {
pub enabled: bool,
pub test_results: Vec<CapabilityTestResult>,
pub capabilities: Vec<String>,
pub needs_rollback: bool,
}