ek-core 0.5.2

Business-agnostic plugin host and actor-over-bus runtime on top of ek-event: capability index with runtime service discovery, per-plugin actor workers, dynamic add/remove with lifecycle broadcasts, one-shot ask/ask_service with contract gates, panic quarantine, five-step close.
Documentation
//! 服务声明与解析(0.2.0 新增):插件自报目录、宿主持【纯路由索引】。

use crate::main_engine::PluginState;
use std::any::{Any, type_name};
use std::time::Duration;

/// 一条服务声明(住回插件本身;宿主仅在 add 时抽 `id` 织入路由索引)。
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ServiceDesc {
    /// 服务标识,如 `order.place`(允许多提供方共享同一 id)。
    pub id: String,
    /// 请求类型名(type_name::<Req>() 自填)。
    pub req_type: String,
    /// 返回类型名(type_name::<Res>() 自填)。
    pub res_type: String,
    /// 人读说明。
    pub doc: String,
    /// 建议超时(可选)。
    pub timeout_hint: Option<Duration>,
}

impl ServiceDesc {
    /// 类型化构造:从 Req/Res 具体类型抓取 type_name。
    pub fn describe<Req, Res>(id: impl Into<String>, doc: impl Into<String>) -> Self
    where
        Req: Any + Send + Sync,
        Res: Any + Send + Sync,
    {
        Self {
            id: id.into(),
            req_type: type_name::<Req>().to_string(),
            res_type: type_name::<Res>().to_string(),
            doc: doc.into(),
            timeout_hint: None,
        }
    }

    /// 附带建议超时。
    pub fn with_timeout(mut self, d: Duration) -> Self {
        self.timeout_hint = Some(d);
        self
    }
}

/// `find_service` 的一条解析结果:索引命中 + 现场明细。
#[derive(Clone, Debug, PartialEq)]
pub struct ProviderRef {
    /// 提供方注册名(ask/ask_service 路由即以此为 target)。
    pub name: String,
    /// 提供方申报版本(空串 = 未声明版本,被动跟随策略不主动迁移)。
    pub version: String,
    /// 提供方当前状态(Ready 亦可被发现,但 ask_service 只路由 Running 者)。
    pub state: PluginState,
    /// 该服务的完整描述(现场取,永远最新)。
    pub service: ServiceDesc,
}

/// 生命周期事件的固定键载荷(订阅 `ePlugUp`/`ePlugDown` 这类不带后缀的固定 type;
/// 另有 `ePlugUp.<名>` 后缀变体,载荷为版本字符串)。
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PlugNotice {
    pub name: String,
    pub version: String,
}