secra_plugins 0.1.32

生产级插件系统 - 插件的生命周期
Documentation
use serde::{Deserialize, Serialize};
use crate::metadata::PluginMetadata;

/// 插件状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PluginStatus {
    /// 已加载但未初始化
    Loaded,
    /// 已初始化但未启动
    Initialized,
    /// 正在运行
    Running,
    /// 已停止
    Stopped,
    /// 已禁用(不处理请求)
    Disabled,
    /// 错误状态
    Error(String),
}

impl PluginStatus {
    /// 检查是否可以初始化
    ///
    /// 检查插件当前状态是否允许执行初始化操作。
    ///
    /// # 返回值
    /// * `bool` - 如果状态为 `Loaded` 返回 `true`,否则返回 `false`
    ///
    /// # 状态要求
    /// 只有 `Loaded` 状态的插件可以初始化。
    ///
    /// # 示例
    /// ```no_run
    /// if status.can_initialize() {
    ///     // 可以初始化
    /// }
    /// ```
    pub fn can_initialize(&self) -> bool {
        matches!(self, PluginStatus::Loaded)
    }
    
    /// 检查是否可以启动
    ///
    /// 检查插件当前状态是否允许执行启动操作。
    ///
    /// # 返回值
    /// * `bool` - 如果状态为 `Initialized` 或 `Stopped` 返回 `true`,否则返回 `false`
    ///
    /// # 状态要求
    /// `Initialized` 和 `Stopped` 状态的插件可以启动。
    ///
    /// # 示例
    /// ```no_run
    /// if status.can_start() {
    ///     // 可以启动
    /// }
    /// ```
    pub fn can_start(&self) -> bool {
        matches!(self, PluginStatus::Initialized | PluginStatus::Stopped)
    }
    
    /// 检查是否可以停止
    ///
    /// 检查插件当前状态是否允许执行停止操作。
    ///
    /// # 返回值
    /// * `bool` - 如果状态为 `Running` 返回 `true`,否则返回 `false`
    ///
    /// # 状态要求
    /// 只有 `Running` 状态的插件可以停止。
    ///
    /// # 示例
    /// ```no_run
    /// if status.can_stop() {
    ///     // 可以停止
    /// }
    /// ```
    pub fn can_stop(&self) -> bool {
        matches!(self, PluginStatus::Running)
    }
    
    /// 检查是否正在运行
    ///
    /// 检查插件是否处于运行状态。
    ///
    /// # 返回值
    /// * `bool` - 如果状态为 `Running` 返回 `true`,否则返回 `false`
    ///
    /// # 示例
    /// ```no_run
    /// if status.is_running() {
    ///     println!("插件正在运行");
    /// }
    /// ```
    pub fn is_running(&self) -> bool {
        matches!(self, PluginStatus::Running)
    }
    
    /// 检查是否处于错误状态
    ///
    /// 检查插件是否处于错误状态。
    ///
    /// # 返回值
    /// * `bool` - 如果状态为 `Error` 返回 `true`,否则返回 `false`
    ///
    /// # 示例
    /// ```no_run
    /// if status.is_error() {
    ///     println!("插件处于错误状态");
    /// }
    /// ```
    pub fn is_error(&self) -> bool {
        matches!(self, PluginStatus::Error(_))
    }
    
    /// 获取状态的字符串表示
    ///
    /// 返回状态的英文字符串表示,用于日志记录和序列化。
    ///
    /// # 返回值
    /// * `&str` - 状态的字符串表示:
    ///   - `Loaded` -> "loaded"
    ///   - `Initialized` -> "initialized"
    ///   - `Running` -> "running"
    ///   - `Stopped` -> "stopped"
    ///   - `Disabled` -> "disabled"
    ///   - `Error(_)` -> "error"
    ///
    /// # 示例
    /// ```no_run
    /// println!("插件状态: {}", status.as_str());
    /// ```
    pub fn as_str(&self) -> &str {
        match self {
            PluginStatus::Loaded => "loaded",
            PluginStatus::Initialized => "initialized",
            PluginStatus::Running => "running",
            PluginStatus::Stopped => "stopped",
            PluginStatus::Disabled => "disabled",
            PluginStatus::Error(_) => "error",
        }
    }
    
    /// 验证状态转换是否有效
    ///
    /// # 参数
    /// * `target` - 目标状态
    ///
    /// # 返回值
    /// * `Result<(), String>` - 成功返回 Ok(()),失败返回错误信息
    pub fn validate_transition(&self, target: &PluginStatus) -> Result<(), String> {
        match (self, target) {
            // 从 Loaded 可以转换到 Initialized, Disabled 或 Error
            (PluginStatus::Loaded, PluginStatus::Initialized) => Ok(()),
            (PluginStatus::Loaded, PluginStatus::Disabled) => Ok(()),
            (PluginStatus::Loaded, PluginStatus::Error(_)) => Ok(()),
            
            // 从 Initialized 可以转换到 Running, Stopped, Disabled 或 Error
            (PluginStatus::Initialized, PluginStatus::Running) => Ok(()),
            (PluginStatus::Initialized, PluginStatus::Stopped) => Ok(()),
            (PluginStatus::Initialized, PluginStatus::Disabled) => Ok(()),
            (PluginStatus::Initialized, PluginStatus::Error(_)) => Ok(()),
            
            // 从 Running 可以转换到 Stopped, Disabled 或 Error
            (PluginStatus::Running, PluginStatus::Stopped) => Ok(()),
            (PluginStatus::Running, PluginStatus::Disabled) => Ok(()),
            (PluginStatus::Running, PluginStatus::Error(_)) => Ok(()),
            
            // 从 Stopped 可以转换到 Running, Disabled 或 Error
            (PluginStatus::Stopped, PluginStatus::Running) => Ok(()),
            (PluginStatus::Stopped, PluginStatus::Disabled) => Ok(()),
            (PluginStatus::Stopped, PluginStatus::Error(_)) => Ok(()),
            
            // 从 Disabled 可以恢复到 Running, Stopped 或 Error
            (PluginStatus::Disabled, PluginStatus::Running) => Ok(()),
            (PluginStatus::Disabled, PluginStatus::Stopped) => Ok(()),
            (PluginStatus::Disabled, PluginStatus::Error(_)) => Ok(()),
            
            // 从 Error 可以恢复到任何状态
            (PluginStatus::Error(_), _) => Ok(()),
            
            // 其他转换无效
            _ => Err(format!("无效的状态转换: {} -> {}", self.as_str(), target.as_str())),
        }
    }
}

impl std::fmt::Display for PluginStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PluginStatus::Loaded => write!(f, "已加载"),
            PluginStatus::Initialized => write!(f, "已初始化"),
            PluginStatus::Running => write!(f, "运行中"),
            PluginStatus::Stopped => write!(f, "已停止"),
            PluginStatus::Disabled => write!(f, "已禁用"),
            PluginStatus::Error(msg) => write!(f, "错误: {}", msg),
        }
    }
}

/// 子插件描述信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChildPluginInfo {
    /// 子插件 ID
    pub id: String,
    /// 子插件名称
    pub name: String,
    /// 子插件版本
    pub version: String,
    /// 子插件路由前缀
    pub route_prefix: Option<String>,
    /// 子插件是否为中间插件(用于分层展示)
    pub is_middle_plugin: bool,
}

impl ChildPluginInfo {
    /// 从插件元数据创建子插件信息
    ///
    /// 从插件的元数据中提取子插件信息,用于在父插件中记录子插件。
    ///
    /// # 参数
    /// * `metadata` - 插件的元数据引用
    ///
    /// # 返回值
    /// * `Self` - 子插件信息实例
    ///
    /// # 提取的字段
    /// * `id`: 从 `metadata.id` 提取
    /// * `name`: 从 `metadata.name` 提取
    /// * `version`: 从 `metadata.version` 提取
    /// * `route_prefix`: 从 `metadata.route_prefix` 提取
    /// * `is_middle_plugin`: 从 `metadata.is_middle_plugin` 提取
    ///
    /// # 示例
    /// ```no_run
    /// let child_info = ChildPluginInfo::from_metadata(&plugin_metadata);
    /// ```
    pub fn from_metadata(metadata: &PluginMetadata) -> Self {
        Self {
            id: metadata.id.clone(),
            name: metadata.name.clone(),
            version: metadata.version.clone(),
            route_prefix: metadata.route_prefix.clone(),
            is_middle_plugin: metadata.is_middle_plugin,
        }
    }
    
    /// 创建构建器
    ///
    /// 使用构建器模式创建子插件信息,允许链式调用设置各个字段。
    ///
    /// # 返回值
    /// * `ChildPluginInfoBuilder` - 子插件信息构建器实例
    ///
    /// # 示例
    /// ```no_run
    /// let child_info = ChildPluginInfo::builder()
    ///     .id("child-plugin".to_string())
    ///     .name("Child Plugin".to_string())
    ///     .version("1.0.0".to_string())
    ///     .build()?;
    /// ```
    pub fn builder() -> ChildPluginInfoBuilder {
        ChildPluginInfoBuilder::default()
    }
}

/// 子插件信息构建器
#[derive(Default)]
pub struct ChildPluginInfoBuilder {
    id: Option<String>,
    name: Option<String>,
    version: Option<String>,
    route_prefix: Option<String>,
    is_middle_plugin: bool,
}

impl ChildPluginInfoBuilder {
    /// 设置子插件 ID
    ///
    /// 设置子插件的唯一标识符。
    ///
    /// # 参数
    /// * `id` - 子插件ID字符串
    ///
    /// # 返回值
    /// * `Self` - 返回自身,支持链式调用
    pub fn id(mut self, id: String) -> Self {
        self.id = Some(id);
        self
    }
    
    /// 设置子插件名称
    ///
    /// 设置子插件的显示名称。
    ///
    /// # 参数
    /// * `name` - 子插件名称字符串
    ///
    /// # 返回值
    /// * `Self` - 返回自身,支持链式调用
    pub fn name(mut self, name: String) -> Self {
        self.name = Some(name);
        self
    }
    
    /// 设置子插件版本
    ///
    /// 设置子插件的版本号。
    ///
    /// # 参数
    /// * `version` - 子插件版本字符串
    ///
    /// # 返回值
    /// * `Self` - 返回自身,支持链式调用
    pub fn version(mut self, version: String) -> Self {
        self.version = Some(version);
        self
    }
    
    /// 设置路由前缀
    ///
    /// 设置子插件的 HTTP 路由前缀。
    ///
    /// # 参数
    /// * `prefix` - 路由前缀字符串
    ///
    /// # 返回值
    /// * `Self` - 返回自身,支持链式调用
    ///
    /// # 注意
    /// 路由前缀是可选的,如果不设置则使用 `None`。
    pub fn route_prefix(mut self, prefix: String) -> Self {
        self.route_prefix = Some(prefix);
        self
    }
    
    /// 设置是否为中间插件
    ///
    /// 设置子插件是否为中间插件。
    ///
    /// # 参数
    /// * `is_middle` - 是否为中间插件
    ///
    /// # 返回值
    /// * `Self` - 返回自身,支持链式调用
    ///
    /// # 默认值
    /// 默认为 `false`。
    pub fn is_middle_plugin(mut self, is_middle: bool) -> Self {
        self.is_middle_plugin = is_middle;
        self
    }
    
    /// 构建子插件信息
    ///
    /// 使用构建器中设置的参数创建 `ChildPluginInfo` 实例。
    /// 构建过程会验证必填字段。
    ///
    /// # 返回值
    /// * `Result<ChildPluginInfo, String>` - 成功时返回子插件信息实例,失败返回错误消息
    ///
    /// # 错误
    /// * 如果必填字段(ID、名称、版本)未设置,返回错误
    ///
    /// # 默认值
    /// * `route_prefix`: 如果不设置,使用 `None`
    /// * `is_middle_plugin`: 默认为 `false`
    ///
    /// # 示例
    /// ```no_run
    /// let child_info = ChildPluginInfoBuilder::default()
    ///     .id("child-plugin".to_string())
    ///     .name("Child Plugin".to_string())
    ///     .version("1.0.0".to_string())
    ///     .build()?;
    /// ```
    pub fn build(self) -> Result<ChildPluginInfo, String> {
        Ok(ChildPluginInfo {
            id: self.id.ok_or("子插件 ID 不能为空")?,
            name: self.name.ok_or("子插件名称不能为空")?,
            version: self.version.ok_or("子插件版本不能为空")?,
            route_prefix: self.route_prefix,
            is_middle_plugin: self.is_middle_plugin,
        })
    }
}