127 lines
5.5 KiB
Markdown
127 lines
5.5 KiB
Markdown
# chongming-worker-rs —— 进程插件 Rust SDK
|
||
|
||
chongming 进程插件线协议([docs/plugin-wire-protocol.md](../../docs/plugin-wire-protocol.md))的 **Rust 参考实现**
|
||
(多语言演进规划阶段 1,见 [docs/multi-language-plugin-plan.md](../../docs/multi-language-plugin-plan.md))。
|
||
|
||
与 Python SDK(`utils/worker/`)行为等价:同一 `<type>` 下可混布部署,网关负载均衡在
|
||
两实现间透明分发。**已通过协议级 15/15 与混布对拍 6/6 端到端验证。**
|
||
|
||
## 模块结构
|
||
|
||
| 模块 | 职责 | 对位(Python SDK) |
|
||
| ---- | ---- | ---- |
|
||
| `config.rs` | 全局 config.toml(`[zenoh].json5_path`)+ 插件 `[workers]` 节展平 + mqtt_topics | `process.py: load_plugin_config` |
|
||
| `descriptor.rs` | 端点 TOML 解析 → 路由描述符(defaults 合并 / subject / path / route_id) | `route_config.py` + `routes_publisher.py` |
|
||
| `envelope.rs` | 请求信封解析(meta.method / user_info / data,非信封载荷按 GET) | `runtime.py` |
|
||
| `error.rs` | 非流式错误格式 / 流式 error 收尾块 | `runtime.py` |
|
||
| `publisher.rs` | 描述符 PUT / DELETE / 10s 周期重发布 | `routes_publisher.py` |
|
||
| `serve.rs` | worker_serve 主流程:liveliness token + Queryable + 信号处理 | `process.py: worker_serve` |
|
||
|
||
## 插件开发三步
|
||
|
||
```rust
|
||
use chongming_worker_rs::prelude::*;
|
||
|
||
let mut registry = HandlerRegistry::new();
|
||
// 普通端点
|
||
registry.register("rsdemo.hello", "GET", |req: Request| async move {
|
||
Ok(Reply::Json(json!({"greeting": "Hello!"})))
|
||
});
|
||
// 流式端点(SSE 逐块)
|
||
registry.register("rsdemo.stream", "POST", |req: Request| async move {
|
||
let stream = async_stream::stream! {
|
||
for i in 0..5 { yield Ok(json!({"index": i})); }
|
||
};
|
||
Ok(Reply::Stream(Box::pin(stream)))
|
||
});
|
||
|
||
serve::serve("rsdemo", Arc::new(registry), ServeOptions::default()).await?;
|
||
```
|
||
|
||
端点 TOML 定义与 Python 插件共用同一套格式(`config/workers/<type>/*.toml`),
|
||
描述符生成规则逐字段对位(`docs/plugin-wire-protocol.md` §2.2)。
|
||
|
||
## 模型生成(TOML 是唯一事实来源)
|
||
|
||
请求/响应模型由端点 TOML 的 `params` / `response_model` 声明**自动生成**
|
||
(对齐 Python `gen_models`,命名约定一致:`hello` + `GET` → `HelloGetRequest`):
|
||
|
||
```bash
|
||
# 项目根目录
|
||
cargo run --bin gen_models -- --types rsdemo,demo --out utils/worker-rs/generated_models.rs
|
||
```
|
||
|
||
生成文件(crate 根 `generated_models.rs`,勿手动修改)每个插件类型一个 mod,
|
||
结构体带 serde derive,字段类型映射对齐网关(str/int/float/bool/any/list/dict)。
|
||
|
||
**一致性保证(比 Python 更强)**:生成文件头部写入 `FINGERPRINT`(端点 TOML 内容 hash)。
|
||
插件启动时(`check_models_fingerprint`)重算指纹比对——**TOML 变更而未重新生成模型
|
||
即告警并提示重跑 gen_models**,杜绝模型与配置漂移。
|
||
|
||
```rust
|
||
// 插件内使用生成模型(强类型 handler)
|
||
let req: generated_models::rsdemo::HelloGetRequest = serde_json::from_value(request.data)?;
|
||
let resp = generated_models::rsdemo::HelloGetResponse {
|
||
greeting: format!("Hello, {}!", req.name),
|
||
worker_id: Some(request.worker_id),
|
||
timestamp: now_ts(),
|
||
};
|
||
```
|
||
|
||
类型映射规则(对齐网关 `route_generator` 的 TYPE_MAP):
|
||
|
||
| TOML 声明 | Rust 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| `str` | `String` | |
|
||
| `int` | `i64` | |
|
||
| `float` | `f64` | |
|
||
| `bool` | `bool` | |
|
||
| `any` | `serde_json::Value` | |
|
||
| `list[X]` / `List[X]` | `Vec<X>` | 递归映射 |
|
||
| `dict[K,V]` / `Dict[K,V]` | `HashMap<K,V>` | 递归映射 |
|
||
| 其他 | `serde_json::Value` | 宽松兜底 |
|
||
|
||
语义对齐:`params` 全部必填;`response_model` 中 `required = false` 的字段生成
|
||
`Option<T>` + `skip_serializing_if`(空值不输出)。
|
||
|
||
## 本地验证
|
||
|
||
前置:本地 Zenoh Router(替代 zenohd,`mode=router` 监听 7447):
|
||
|
||
```bash
|
||
.venv/bin/python utils/worker-rs/scripts/zenoh_router.py &
|
||
```
|
||
|
||
协议级端到端验证(路由注册 / RPC / 流式 / 错误 / 摘除 / 自愈,15 项断言):
|
||
|
||
```bash
|
||
cargo build --examples
|
||
.venv/bin/python utils/worker-rs/scripts/verify_e2e.py --type rsdemo
|
||
```
|
||
|
||
Python + Rust 同 type 混布对拍(描述符 hash 一致 / 双副本发现 / RPC 等价 / 互不干扰):
|
||
|
||
```bash
|
||
.venv/bin/python utils/worker-rs/scripts/verify_mixed.py
|
||
```
|
||
|
||
参考插件(`examples/demo.rs`)支持两个 type:
|
||
|
||
```bash
|
||
# 项目根目录(config.toml 相对路径)
|
||
utils/worker-rs/target/debug/examples/demo --type rsdemo # 独立演示插件
|
||
utils/worker-rs/target/debug/examples/demo --type demo # 与 Python demo 混布对拍
|
||
```
|
||
|
||
**独立插件形态**(插件开发者实际使用的方式):`workers/rsdemo/` 是一个完整独立的
|
||
插件 crate(path 依赖本 SDK),与 Python 示例 `workers/demo/` 对位,含端点实现、
|
||
生成模型与说明文档——建议新插件以此为模板。
|
||
|
||
## 与 Python SDK 的差异(有意为之)
|
||
|
||
| 差异 | 说明 |
|
||
| ---- | ---- |
|
||
| 契约校验 | Python 在 worker 进程内做 TOML↔注册表↔模型三方校验(硬失败退出);Rust 侧降级为**发布前自检**:无 handler 的端点告警并跳过,不发布残缺路由 |
|
||
| 模型生成 | Rust 有 gen_models 等价物(`--bin gen_models`):从端点 TOML 生成强类型结构体 + **启动时指纹校验**(TOML 变更未重生成即告警,比 Python 只查模型存在性更强) |
|
||
| handler 注入 | worker_id 经 `Request.worker_id` 注入(Python 为函数参数);user_info 经 `Request.user_info` |
|