2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00
2026-08-31 17:18:03 +08:00

chongming-worker-rs —— 进程插件 Rust SDK

chongming 进程插件线协议(docs/plugin-wire-protocol.md)的 Rust 参考实现 (多语言演进规划阶段 1,见 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

插件开发三步

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):

# 项目根目录
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,杜绝模型与配置漂移。

// 插件内使用生成模型(强类型 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):

.venv/bin/python utils/worker-rs/scripts/zenoh_router.py &

协议级端到端验证(路由注册 / RPC / 流式 / 错误 / 摘除 / 自愈,15 项断言):

cargo build --examples
.venv/bin/python utils/worker-rs/scripts/verify_e2e.py --type rsdemo

Python + Rust 同 type 混布对拍(描述符 hash 一致 / 双副本发现 / RPC 等价 / 互不干扰):

.venv/bin/python utils/worker-rs/scripts/verify_mixed.py

参考插件(examples/demo.rs)支持两个 type:

# 项目根目录(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
S
Description
No description provided
Readme
81 KiB
Languages
Rust 84.4%
Python 15.1%
Shell 0.5%