secra_plugins 0.1.32

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

use crate::error::{PluginManagerError, PluginManagerResult};
use crate::status::PluginStatus;
use crate::manager::types::{PluginInstance, PluginMap};
use crate::manager::lifecycle_ops::stop_single_plugin;
use tracing::{debug, error, info, trace, warn};

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

    let stop_order = {
        trace!("获取读锁,查找需要停止的插件");
        let plugins = plugins.read().await;
        let mut child_ids = Vec::new();
        let mut parent_ids = Vec::new();

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

        let parent_count = parent_ids.len();
        child_ids.extend(parent_ids);
        debug!("需要停止的插件: {} 个子插件, {} 个主插件", 
               child_ids.len() - parent_count, parent_count);
        child_ids
    };

    for plugin_id in stop_order {
        trace!("停止插件: {}", plugin_id);
        let mut plugins = plugins.write().await;

        if let Some(plugin_instance) = plugins.get_mut(&plugin_id) {
            stop_single_plugin(plugin_id, plugin_instance, timeout_secs).await;
        }
    }

    info!("插件停止完成");
    trace!("批量停止插件流程完成");
    Ok(())
}

/// 停止单个插件
///
/// 停止指定的插件。插件必须处于 `Running` 状态才能停止。
/// 停止过程会调用插件的 `stop()` 方法。
///
/// # 参数
/// * `plugins` - 插件实例的共享映射表,使用 `Arc<RwLock<>>` 保证线程安全
/// * `plugin_id` - 要停止的插件ID
/// * `timeout_secs` - 停止的超时时间(秒)
///
/// # 返回值
/// * `PluginManagerResult<()>` - 成功时返回 `Ok(())`
///
/// # 错误
/// * `PluginManagerError::NotFound` - 如果指定的插件不存在
/// * `PluginManagerError::StopFailed` - 如果停止失败(插件状态变为 `Error`)
///
/// # 状态转换
/// * `Running` -> `Stopped`: 停止成功
/// * `Running` -> `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()));
/// stop_plugin(plugins, "my-plugin", 30).await?;
/// # }
/// ```
pub async fn stop_plugin(
    plugins: PluginMap,
    plugin_id: &str,
    timeout_secs: u64,
) -> PluginManagerResult<()> {
    trace!("开始停止单个插件: {} (超时: {}s)", plugin_id, timeout_secs);
    
    let mut plugins = plugins.write().await;

    let plugin_instance = plugins.get_mut(plugin_id)
        .ok_or_else(|| {
            error!("插件不存在: {}", plugin_id);
            PluginManagerError::not_found(plugin_id)
        })?;
    
    debug!("找到插件实例: {} (状态: {:?})", 
           plugin_instance.metadata.name, plugin_instance.status);

    stop_single_plugin(plugin_id.to_string(), plugin_instance, timeout_secs).await;

    if let Some(instance) = plugins.get(plugin_id) {
        if let PluginStatus::Error(err) = &instance.status {
            error!("插件停止失败: {} - {}", plugin_id, err);
            return Err(PluginManagerError::StopFailed(err.clone()));
        }
    }

    trace!("插件停止流程完成");
    Ok(())
}