secra_plugins 0.1.32

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

use crate::error::{PluginManagerError, PluginManagerResult};
use crate::status::PluginStatus;
use crate::manager::types::{PluginInstance, PluginMap};
use crate::manager::validation::sanitize_plugin_name;
use tokio::time::{timeout, Duration};
use tracing::{debug, error, info, trace, warn};

/// 启动所有插件
///
/// 批量启动所有处于 `Initialized` 状态的插件。启动顺序会优先处理主插件,
/// 然后处理子插件,确保依赖关系的正确启动。
///
/// # 参数
/// * `plugins` - 插件实例的共享映射表,使用 `Arc<RwLock<>>` 保证线程安全
/// * `timeout_secs` - 每个插件启动的超时时间(秒)
///
/// # 返回值
/// * `PluginManagerResult<()>` - 成功时返回 `Ok(())`
///
/// # 行为
/// * 只启动状态为 `Initialized` 的插件
/// * 按照主插件优先、子插件其次的顺序启动
/// * 如果某个插件启动失败,会将其状态设置为 `Error`,但继续启动其他插件
/// * 启动超时也会将插件状态设置为 `Error`
///
/// # 状态转换
/// * `Initialized` -> `Running`: 启动成功
/// * `Initialized` -> `Error`: 启动失败或超时
///
/// # 示例
/// ```no_run
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
/// use std::collections::HashMap;
/// 
/// # async fn example() {
/// let plugins = Arc::new(RwLock::new(HashMap::new()));
/// start_all_plugins(plugins, 30).await?;
/// # }
/// ```
pub async fn start_all_plugins(
    plugins: PluginMap,
    timeout_secs: u64,
) -> PluginManagerResult<()> {
    trace!("开始批量启动插件,超时时间: {}s", timeout_secs);
    info!("开始启动插件...");

    let start_order = {
        trace!("获取读锁,查找需要启动的插件");
        let plugins = plugins.read().await;
        let mut start_ids = Vec::new();
        let mut child_ids = Vec::new();

        for (id, instance) in plugins.iter() {
            if instance.status == PluginStatus::Initialized {
                if instance.metadata.is_sub_plugin {
                    trace!("发现需要启动的子插件: {}", id);
                    child_ids.push(id.to_string());
                } else {
                    trace!("发现需要启动的主插件: {}", id);
                    start_ids.push(id.to_string());
                }
            }
        }

        let child_count = child_ids.len();
        start_ids.extend(child_ids);
        debug!("需要启动的插件: {} 个主插件, {} 个子插件", 
               start_ids.len() - child_count, child_count);
        start_ids
    };

    let mut success_count = 0;
    let mut failure_count = 0;
    
    for plugin_id in start_order {
        trace!("启动插件: {}", plugin_id);
        let mut plugins = plugins.write().await;

        if let Some(plugin_instance) = plugins.get_mut(&plugin_id) {
            if plugin_instance.status == PluginStatus::Initialized {
                debug!("调用插件 start 方法: {}", plugin_id);
                let start_result = timeout(
                    Duration::from_secs(timeout_secs),
                    plugin_instance.plugin.start()
                ).await;

                match start_result {
                    Ok(Ok(_)) => {
                        if plugin_instance.status.validate_transition(&PluginStatus::Running).is_ok() {
                            plugin_instance.status = PluginStatus::Running;
                            info!("插件启动成功: {}", plugin_id);
                            success_count += 1;
                        } else {
                            plugin_instance.status = PluginStatus::Error("状态转换无效".to_string());
                            error!("插件 {} 状态转换无效", plugin_id);
                            failure_count += 1;
                        }
                    }
                    Ok(Err(e)) => {
                        plugin_instance.status = PluginStatus::Error(e.to_string());
                        error!("插件启动失败 {}: {}", plugin_id, e);
                        failure_count += 1;
                    }
                    Err(_) => {
                        plugin_instance.status = PluginStatus::Error("启动超时".to_string());
                        error!("插件启动超时: {} (超时时间: {}s)", plugin_id, timeout_secs);
                        failure_count += 1;
                    }
                }
            } else {
                trace!("插件 {} 状态不是 Initialized,跳过: {:?}", plugin_id, plugin_instance.status);
            }
        }
    }

    info!("插件启动完成 - 成功: {}, 失败: {}, 总计: {}", 
          success_count, failure_count, success_count + failure_count);
    trace!("批量启动插件流程完成");
    Ok(())
}

/// 启动单个插件
///
/// 启动指定的插件。插件必须处于 `Initialized` 状态才能启动。
/// 启动过程会调用插件的 `start()` 方法。
///
/// # 参数
/// * `plugins` - 插件实例的共享映射表,使用 `Arc<RwLock<>>` 保证线程安全
/// * `plugin_id` - 要启动的插件ID
/// * `timeout_secs` - 启动的超时时间(秒)
///
/// # 返回值
/// * `PluginManagerResult<()>` - 成功时返回 `Ok(())`
///
/// # 错误
/// * `PluginManagerError::NotFound` - 如果指定的插件不存在
/// * `PluginManagerError::StateError` - 如果插件状态不正确或状态转换无效
/// * `PluginManagerError::ExecutionError` - 如果启动失败或超时
///
/// # 状态转换
/// * `Initialized` -> `Running`: 启动成功
/// * `Initialized` -> `Error`: 启动失败或超时
///
/// # 示例
/// ```no_run
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
/// use std::collections::HashMap;
/// 
/// # async fn example() {
/// let plugins = Arc::new(RwLock::new(HashMap::new()));
/// start_plugin(plugins, "my-plugin", 30).await?;
/// # }
/// ```
pub async fn start_plugin(
    plugins: PluginMap,
    plugin_id: &str,
    timeout_secs: u64,
) -> PluginManagerResult<()> {
    trace!("开始启动单个插件: {} (超时: {}s)", plugin_id, timeout_secs);
    
    let sanitized_plugin_id = sanitize_plugin_name(plugin_id)?;
    debug!("插件ID清理: {} -> {}", plugin_id, sanitized_plugin_id);

    let mut plugins = plugins.write().await;

    if let Some(plugin_instance) = plugins.get_mut(&sanitized_plugin_id) {
        debug!("找到插件实例: {} (状态: {:?})", 
               plugin_instance.metadata.name, plugin_instance.status);
        
        if plugin_instance.status == PluginStatus::Initialized {
            trace!("插件状态正确,调用 start 方法");
            let start_result = timeout(
                Duration::from_secs(timeout_secs),
                plugin_instance.plugin.start()
            ).await;

            match start_result {
                Ok(Ok(_)) => {
                    if plugin_instance.status.validate_transition(&PluginStatus::Running).is_ok() {
                        plugin_instance.status = PluginStatus::Running;
                        info!("插件启动成功: {}", sanitized_plugin_id);
                        trace!("插件状态已更新为 Running");
                    } else {
                        plugin_instance.status = PluginStatus::Error("状态转换无效".to_string());
                        error!("插件 {} 状态转换无效", sanitized_plugin_id);
                        return Err(PluginManagerError::StateError("状态转换无效".to_string()));
                    }
                }
                Ok(Err(e)) => {
                    plugin_instance.status = PluginStatus::Error(e.to_string());
                    error!("插件启动失败 {}: {}", sanitized_plugin_id, e);
                    return Err(PluginManagerError::ExecutionError(
                        format!("插件启动失败: {}", e)
                    ));
                }
                Err(_) => {
                    plugin_instance.status = PluginStatus::Error("启动超时".to_string());
                    error!("插件启动超时: {} (超时时间: {}s)", sanitized_plugin_id, timeout_secs);
                    return Err(PluginManagerError::ExecutionError(
                        format!("插件启动超时(超时时间: {}秒)", timeout_secs)
                    ));
                }
            }
        } else {
            warn!("插件 {} 状态不正确,无法启动: {:?}", sanitized_plugin_id, plugin_instance.status);
            return Err(PluginManagerError::StateError(
                format!("插件状态不正确,无法启动: {:?}", plugin_instance.status)
            ));
        }
    } else {
        error!("插件不存在: {}", plugin_id);
        return Err(PluginManagerError::not_found(plugin_id));
    }

    trace!("插件启动流程完成");
    Ok(())
}