ek-core 0.1.0

Business-agnostic plugin host and actor-over-bus runtime on top of ek-event: single-registry plugins, explicit deps with topological start, per-plugin actor workers, one-shot request/reply, panic quarantine, five-step close.
Documentation

ek-core

Actor-over-Bus 插件宿主。在已发布的 ek-event 事件底座之上,提供一套业务无关的插件框架:单表注册、显式依赖、拓扑启动、独立线程 actor、一次性请求应答、故障熔断与五步关停。

设计立场:ek-core 不依赖任何业务;事件总线只转发、永不执行业务逻辑;插件之间不直调,一切通信走事件。

特性

  • 统一单表注册:add_plugin / get_plugin / get_state / get_typed::<T>(类型安全下转型),无 dual-API。
  • 显式依赖:deps() 声明,注册期校验存在性,start() 按 Kahn 拓扑序装配(环报 DepCycle),close() 逆序回收。
  • 每插件一个 actor:bounded(默认 1024,可覆写)邮箱 + 专用 ek-worker.<name> 线程,on_mail 是插件唯一收信口,天然串行化。
  • 唯一出口:ctx.put(广播)/ ctx.ask<Req, Res>(eReq + 一次性信道)/ ctx.notify(eTo)/ ctx.write_log(内置 LogPlugin)。
  • 快失败请求:ask 三重失败面——目标不在(预检+断连,即时 TargetGone)、等满(Timeout)、契约不匹配(InvalidPayload);handler panic 时回包信道关闭 → 发起方立即感知。
  • 故障熔断:handler 连续 panic×3(处理成功即复位)→ 插件隔离为 Quarantined,并发 ePlugQDown.<name> 广播 + eLog 双告警;邻居插件毫发无损。
  • 背压可观:邮箱满即丢弃计数 + 每 128 次溢出节流 eLog;mail_stats 随时可查。
  • 五步关停:卸 forwarder → on_stop → 关邮箱 → worker 排空 → join(带超时,超时告警绝不硬等)。

示例

use ek_core::{MainEngine, Plugin, PluginContext, PluginState, AskError, e_req_type};
use ek_event::Event;
use std::borrow::Cow;
use std::time::Duration;
use std::sync::Arc;
use std::any::Any;

// 合约契约类型(业务 crate 自备,ek-core 一无所知)
#[derive(Clone, Copy, Debug)] struct Ping { id: u64 }
#[derive(Clone, Copy, Debug)] struct Pong { id: u64 }

struct Broker { name: String }

impl Plugin for Broker {
    fn name(&self) -> &str { &self.name }
    fn routes(&self) -> Vec<Cow<'static, str>> { vec![Cow::Owned(e_req_type("broker"))] }
    fn on_mail(&self, event: &Event) {
        ek_core::envelope::Envelope::handle::<Ping, Pong>(event, |p| Pong { id: p.id });
    }
}

struct Client {
    name: String,
    broker: String,
}

// ... client 在 on_mail 里(on_init 缓存 ctx):
//   let r = ctx.ask::<Ping, Pong>("broker", Ping { id }, Duration::from_millis(500));
//   Ok(Pong) / Err(Timeout|TargetGone|InvalidPayload)

fn main() {
    let engine = MainEngine::new(None);
    engine.add_plugin(Arc::new(Broker { name: "broker".into() })).unwrap();
    // engine.add_plugin(...) client(deps = ["broker"])
    engine.start().unwrap();
    // ... 收发事件 ...
    engine.close_all(Duration::from_secs(2)); // 五步关停 + 停总线
}

纪律(协议层)

  1. 收:只有 on_mail 一个入口;订阅面由 routes() 静态声明(v0.1 不支持运行期动态订阅)。
  2. 发:只有 ctx.put / ask / notify / write_log 四个出口;ask 禁止自呼(自己等自己的回包会等到超时)。
  3. 请求义务:Envelope::handle 成功回 Ok(Res)、契约错型回 Err(InvalidPayload);handler panic 由断连信号传达。
  4. 宿主无业务方法;管理类操作(add/remove/start/close)按串行使用设计。

元信息

案例设计文档:DESIGN.md;验收细节:TESTPLAN.md。