secra_plugins 0.1.32

生产级插件系统 - 插件的生命周期
Documentation
//! 插件生命周期操作相关方法

use crate::config::PluginConfig;
use crate::error::{PluginManagerError, PluginManagerResult};
use crate::status::PluginStatus;
use super::types::PluginInstance;
use tokio::time::{timeout, Duration};
use tracing::{debug, error, info, trace, warn};

/// 停止单个插件(内部方法)
///
/// 停止指定的插件实例。这是插件停止操作的内部实现,被 `stop_plugin` 和 `stop_all_plugins` 调用。
/// 只对状态为 `Running` 的插件执行停止操作。
///
/// # 参数
/// * `plugin_id` - 插件ID,用于日志记录
/// * `plugin_instance` - 要停止的插件实例(可变引用)
/// * `timeout_secs` - 停止操作的超时时间(秒)
///
/// # 行为
/// * 只处理状态为 `Running` 的插件
/// * 使用 tracing span 注入插件上下文信息(ID、指纹、版本)
/// * 调用插件的 `stop()` 方法(带超时保护)
/// * 根据执行结果更新插件状态:
///   - 成功:`Running` -> `Stopped`
///   - 失败:`Running` -> `Error`
///   - 超时:`Running` -> `Error`
///
/// # 状态转换
/// * `Running` -> `Stopped`: 停止成功
/// * `Running` -> `Error`: 停止失败或超时
///
/// # 日志
/// 使用 tracing 记录详细的停止过程,包括插件上下文信息,便于问题追踪。
///
/// # 示例
/// ```no_run
/// # async fn example() {
/// // 假设 plugin_instance 是已获取的插件实例引用
/// stop_single_plugin("my-plugin".to_string(), &mut plugin_instance, 30).await;
/// # }
/// ```
pub async fn stop_single_plugin(
    plugin_id: String,
    plugin_instance: &mut PluginInstance,
    timeout_secs: u64,
) {
    trace!("停止单个插件: {} (超时: {}s)", plugin_id, timeout_secs);
    
    // 只停止状态为 Running 的插件
    if plugin_instance.status == PluginStatus::Running {
        // 提取插件的指纹和版本信息,用于日志追踪和上下文注入
        let fingerprint = plugin_instance.fingerprint.clone();
        let plugin_version = plugin_instance.metadata.version.clone();

        debug!("插件信息 - ID: {}, 版本: {}, 指纹: {}", 
               plugin_id, plugin_version, fingerprint);

        // 使用 tracing span 注入插件上下文信息
        let span = tracing::info_span!(
            "plugin_stop",
            plugin_id = %plugin_id,
            fingerprint = %fingerprint,
            plugin_version = %plugin_version
        );
        let _guard = span.enter();

        // 调用插件的 stop() 方法执行停止操作(带超时保护)
        trace!("调用插件 stop 方法");
        let stop_result = timeout(
            Duration::from_secs(timeout_secs),
            plugin_instance.plugin.stop()
        ).await;

        match stop_result {
            Ok(Ok(_)) => {
                // 验证状态转换
                if plugin_instance.status.validate_transition(&PluginStatus::Stopped).is_ok() {
                    plugin_instance.status = PluginStatus::Stopped;
                    info!("插件停止成功: {}", plugin_id);
                    trace!("插件状态已更新为 Stopped");
                } else {
                    plugin_instance.status = PluginStatus::Error("状态转换无效".to_string());
                    error!("插件 {} 状态转换无效", plugin_id);
                }
            }
            Ok(Err(e)) => {
                plugin_instance.status = PluginStatus::Error(e.to_string());
                error!("插件停止失败 {}: {}", plugin_id, e);
            }
            Err(_) => {
                plugin_instance.status = PluginStatus::Error("停止超时".to_string());
                error!("插件停止超时: {} (超时时间: {}s)", plugin_id, timeout_secs);
            }
        }
    } else {
        debug!("插件 {} 未运行,跳过停止操作 (状态: {:?})", plugin_id, plugin_instance.status);
    }
}

/// 初始化单个插件(内部方法)
///
/// 初始化指定的插件实例。这是插件初始化操作的内部实现。
/// 使用默认配置(`enabled = true`)调用插件的 `initialize()` 方法。
///
/// # 参数
/// * `plugin_instance` - 要初始化的插件实例(可变引用)
///
/// # 返回值
/// * `Result<(), Box<dyn std::error::Error>>` - 初始化成功返回 `Ok(())`
///
/// # 错误
/// * 如果插件初始化失败,返回包含错误信息的 `Err`
///
/// # 行为
/// * 创建默认插件配置,设置 `enabled = true`
/// * 调用插件的 `initialize()` 方法
/// * 如果初始化失败,返回格式化的错误信息
///
/// # 注意
/// 此函数不更新插件状态,状态更新由调用者负责。
/// 这允许调用者根据初始化结果灵活处理状态转换。
///
/// # 示例
/// ```no_run
/// # async fn example() {
/// // 假设 plugin_instance 是已获取的插件实例引用
/// match initialize_single_plugin(&mut plugin_instance).await {
///     Ok(_) => println!("插件初始化成功"),
///     Err(e) => println!("插件初始化失败: {}", e),
/// }
/// # }
/// ```
pub async fn initialize_single_plugin(
    plugin_instance: &mut PluginInstance,
) -> Result<(), Box<dyn std::error::Error>> {
    trace!("初始化单个插件: {}", plugin_instance.metadata.id);
    
    // 创建默认插件配置
    let mut config = PluginConfig::default();
    config.enabled = true;
    debug!("创建默认配置,enabled = true");

    // 调用插件的初始化方法
    trace!("调用插件 initialize 方法");
    plugin_instance
        .plugin
        .initialize(config)
        .await
        .map_err(|e| {
            error!("插件初始化失败: {} - {}", plugin_instance.metadata.id, e);
            format!("插件初始化失败: {}", e)
        })?;

    debug!("插件初始化成功: {}", plugin_instance.metadata.id);
    Ok(())
}