use crate::error::{PluginManagerError, PluginManagerResult};
use crate::manager::types::PluginMap;
use actix_web::web;
use tracing::{debug, error, info, trace, warn};
use futures::executor::block_on;
pub async fn register_all_plugin_routes(
plugins: PluginMap,
cfg: &mut web::ServiceConfig,
) -> PluginManagerResult<()> {
trace!("开始注册所有插件路由");
info!("开始注册插件路由...");
let plugin_routes: Vec<(String, String, Option<String>, bool)> = {
trace!("获取读锁,查找需要注册路由的插件");
let plugins = plugins.read().await;
plugins
.iter()
.filter_map(|(id, instance)| {
if instance.status.is_running() && instance.metadata.has_routes() {
trace!("发现需要注册路由的插件: {} (路由前缀: {:?})",
id, instance.metadata.route_prefix);
Some((
id.clone(),
instance.metadata.name.clone(),
instance.metadata.route_prefix.clone(),
instance.metadata.is_sub_plugin,
))
} else {
None
}
})
.collect()
};
if plugin_routes.is_empty() {
info!("没有需要注册路由的插件");
return Ok(());
}
let mut sorted_routes = plugin_routes;
sorted_routes.sort_by(|a, b| {
match (a.3, b.3) {
(false, true) => std::cmp::Ordering::Less,
(true, false) => std::cmp::Ordering::Greater,
_ => a.0.cmp(&b.0)
}
});
debug!("路由注册顺序已排序");
let total_count = sorted_routes.len();
info!("发现 {} 个插件需要注册路由", total_count);
let mut success_count = 0;
let mut failure_count = 0;
for (plugin_id, plugin_name, route_prefix, _) in sorted_routes {
trace!("注册插件路由: {} (路由前缀: {:?})", plugin_id, route_prefix);
let register_result = {
let plugins = plugins.read().await;
let plugin_instance = plugins.get(&plugin_id);
match plugin_instance {
Some(instance) if instance.status.is_running() => {
debug!("调用插件 register_routes 方法: {}", plugin_id);
let result = instance.plugin.register_routes(cfg);
drop(plugins);
result
}
_ => {
drop(plugins);
warn!(
plugin_id = %plugin_id,
"插件不存在或状态已变更,跳过路由注册"
);
continue;
}
}
};
match register_result {
Ok(_) => {
success_count += 1;
info!(
plugin_id = %plugin_id,
plugin_name = %plugin_name,
route_prefix = ?route_prefix,
"插件路由注册成功"
);
trace!("路由注册成功: {}", plugin_id);
}
Err(e) => {
failure_count += 1;
error!(
plugin_id = %plugin_id,
plugin_name = %plugin_name,
route_prefix = ?route_prefix,
error = %e,
"插件路由注册失败"
);
}
}
}
info!(
success_count = success_count,
failure_count = failure_count,
total_count = total_count,
"插件路由注册完成"
);
if failure_count > 0 {
warn!(
"有 {} 个插件的路由注册失败,但已继续注册其他插件",
failure_count
);
}
trace!("路由注册流程完成");
Ok(())
}
pub fn register_all_plugin_routes_sync(
plugins: PluginMap,
cfg: &mut web::ServiceConfig,
) -> PluginManagerResult<()> {
match tokio::runtime::Handle::try_current() {
Ok(handle) => {
let _guard = handle.enter();
block_on(register_all_plugin_routes(plugins, cfg))
}
Err(_) => {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| {
PluginManagerError::Io(
std::io::Error::new(
std::io::ErrorKind::Other,
format!("无法创建 Tokio 运行时: {}", e)
)
)
})?;
rt.block_on(register_all_plugin_routes(plugins, cfg))
}
}
}