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 验收记录(TESTPLAN)

版本 0.1.0。运行方式:`cargo test`(依赖 crates.io 的 ek-event 0.1.0)。
最终状态:**19 用例全绿,3× 重复 0 失败;`cargo clippy --all-targets -- -D warnings` EXIT 0。**

## 1. 用例矩阵与结果

### host_lifecycle(5)

| 用例 | 断言要点 | 结果 |
| --- | --- | --- |
| HL1 注册校验 | 空/数字开头/空白/非 ASCII/33 字符 → `IllegalName`;重名 → `Duplicate`;deps 缺 → `UnknownDep`;自依赖 → `DepCycle`;start 后 add → `HostStarted`;查询 Ready | ✅ |
| HL2 拓扑序/逆序 | B→A→C 依赖链:start 记录 b,a,c;close 记录 c,a,b;close 后表空、状态 None | ✅ |
| HL3 关停静默 | close 后总线上 put 不再进插件 | ✅ |
| HL4 不回放 | start 前流出事件不回放(对齐 g3);start 后事件逐速送达 | ✅(依赖 ek-event start() 幂等,receiver-take 守卫) |
| HL5 信息/统计 | get_state / mail_stats 可查 | ✅ |

### actor_routing(2)

| 用例 | 断言要点 | 结果 |
| --- | --- | --- |
| AR1 FIFO+worker 线程探针 | 200 事件保序;on_mail 全部发生在 `ek-worker.oms`(分发线程零业务) | ✅ |
| AR2 订阅面隔离 | pa/pb 各 3 条,互不串门 | ✅ |

### ask_oneshot(5)

| 用例 | 断言要点 | 结果 |
| --- | --- | --- |
| AO1 并发配对 | 4 个 asker worker 并行 ask,100 次按 id 精确配对;broker 精确处理 100 | ✅ |
| AO2 超时 | 目标处理 600ms > timeout 200ms → `Err(Timeout)`,耗时贴近 | ✅ |
| AO3 错型 | 载荷契约不匹配 → B 侧回 `InvalidPayload`,A 侧类型自查 | ✅ |
| AO4 目标不在 | 预检立即 `TargetGone`(<100ms,不烧超时) | ✅ |
| AO5 panic 断连 | 目标 handler panic → 信封 drop → 快速 `TargetGone`(<400ms);单次 panic 不熔断(目标仍 Running) | ✅ |

### fault_isolation(6)

| 用例 | 断言要点 | 结果 |
| --- | --- | --- |
| FI1 熔断检疫 | 连 3 panic → `Quarantined`;`ePlugQDown.p3` ×1;eLog 含 quarantined;邻居完好;检疫后不再收邮件 | ✅ |
| FI2 慢邻居 | 80ms/事件的慢 worker 不拖累其他插件(fast 应答完成时 slow 仍在处理第 1 件) | ✅ |
| FI3 背压 | cap=32 + 200 突发:processed + spilled == 200 守恒;溢出为多数 | ✅ |
| FI4 关停超时 | 忙 worker(3s)下 close(200ms) 快速返回<1.5s;剥离后稍后排空自退 | ✅ |
| FI5 熔断后 on_stop(F1 修正) | Quarantined 插件 close 仍调 on_stop,Ready 不调 | ✅ |
| FI6 连续语义(F3 修正) | 3 次被成功处理隔开的 panic 不熔断;连 3 panic 即熔断;累计统计面=6 | ✅ |

### concurrency_storm(1)

| 用例 | 断言要点 | 结果 |
| --- | --- | --- |
| CS1 全路径风暴 | 2 生产线程 ×5k(限速 25/2ms)+ 80 并发 ask(4 asker)+ 50 notify + 200 轮 get_state/mail_stats 轮询;终态:两订阅者各 10000、零溢出(spilled==0)、80 ask 精确配对、全部插件 Running、零死锁 | ✅ |

## 2. 方法纪律

- 零业务依赖:全部测试用测试本地结构体(与 ek-event 生态用例同一惯例),不 import 任何业务 crate。
- `wait_until(轮询)` 助手,绝对不使用 `sleep(断言)`;时间裕量仅在"消除竞态"的文档型前提(HL4 的 200ms)首次出现。
- 真断言错误路径用 `matches!` 精确匹配变体;数值路径用 id 配对。稳定性以 3× 重复运行验证。

## 3. 失败记录 → 修复映射(执行全程)

| 阶段 | 记录 | 修复 |
| --- | --- | --- |
| 二轮方案审核 | #1 forwarder_ids 缺失 / #2 TargetGone 宣称过强 / #3 ctx.engine 访问器矛盾 / #4 eReq 溢出语义未定 / #5 remove 策略未定 / #6 forwarder 短路 / #7 头阻塞 | 全部落实现 + 文档 + 3 项由用户拍板(允许 remove / cap 覆写 / 头阻塞接受) |
| 编译期 | Event 无 Clone(R3)→ forwarder 手工复制/envelope Ok/Err 泛型推断/OneshotSender &self(R2)/registry indeg 索引/get_typed Arc clone | 全部按编 error 修复 |
| 执行期 | R1 信封双层泛型错型不可达 → 非泛型信封抹平;R4 CS1 守恒断言与 D5 冲突 → 限速+spilled==0 | 见 DESIGN §3 |
| 执行后复审 | F1 on_stop 判据(Quarantined/Exited 也调);F2 禁自呼文档;F3 连续 panic 语义;F4 eReq 溢出文档口径;F5 注释乱码 | 全部已修并新增 FI-5/FI-6 用例锁语义 |

## 4. 基准与局限

- 待办(未来测评):forwarder `Event` 手工复制在百万级/秒下的 String 重分配压力;若成为瓶颈,启用 ek-event 0.2 候选项:`event_type` 改 `Arc<str>`,或原生「订阅直达邮箱」API。
- 已知接受的取舍见 DESIGN §5;暂不支持运行期动态订阅。
- 极端并发下 `close + remove` 双调窗口:宿主管理操作按串行使用约定(文档已写)。