use crate::error::{PluginManagerError, PluginManagerResult};
use crate::manager::types::PluginMap;
use crate::manager::executor::validate_execute_params;
use crate::manager::validation::sanitize_plugin_name;
use tokio::time::{timeout, Duration};
use tracing::{debug, error, info, trace, warn};
pub async fn execute_plugin(
plugins: PluginMap,
plugin_id: &str,
action: &str,
params: serde_json::Value,
timeout_secs: u64,
) -> PluginManagerResult<serde_json::Value> {
trace!("开始执行插件功能 - 插件: {}, 动作: {}, 超时: {}s",
plugin_id, action, timeout_secs);
let sanitized_plugin_id = sanitize_plugin_name(plugin_id)?;
debug!("插件ID清理: {} -> {}", plugin_id, sanitized_plugin_id);
validate_execute_params(action)?;
debug!("执行参数验证通过");
let execute_result = {
trace!("获取读锁,查找插件实例");
let plugins = plugins.read().await;
let plugin_instance = plugins.get(&sanitized_plugin_id)
.ok_or_else(|| {
error!("插件不存在: {}", plugin_id);
PluginManagerError::not_found(plugin_id)
})?;
debug!("找到插件实例: {} (状态: {:?})",
plugin_instance.metadata.name, plugin_instance.status);
if !plugin_instance.status.is_running() {
warn!("插件 {} 未运行,当前状态: {}", plugin_id, plugin_instance.status);
return Err(PluginManagerError::StateError(
format!(
"插件 {} 未运行,当前状态: {}",
plugin_id,
plugin_instance.status
)
));
}
let plugin_name = &plugin_instance.metadata.name;
info!(
plugin_id = %sanitized_plugin_id,
plugin_name = %plugin_name,
action = %action,
timeout = timeout_secs,
"执行插件功能"
);
trace!("开始调用插件 execute 方法");
timeout(
Duration::from_secs(timeout_secs),
plugin_instance.plugin.execute(action, params)
).await
};
match execute_result {
Ok(Ok(result)) => {
info!(
plugin_id = %sanitized_plugin_id,
action = %action,
"插件功能执行成功"
);
trace!("插件功能执行完成,返回结果");
Ok(result)
}
Ok(Err(e)) => {
error!(
plugin_id = %sanitized_plugin_id,
action = %action,
error = %e,
"插件功能执行失败"
);
Err(PluginManagerError::ExecutionError(
format!("插件 {} 执行失败: {}", plugin_id, e)
))
}
Err(_) => {
error!(
plugin_id = %sanitized_plugin_id,
action = %action,
timeout = timeout_secs,
"插件功能执行超时"
);
Err(PluginManagerError::ExecutionError(
format!(
"插件 {} 执行超时(超时时间: {}秒)",
plugin_id,
timeout_secs
)
))
}
}
}