From b5aa00872916d9e9be3f2273b1dd1de4bbb6ff47 Mon Sep 17 00:00:00 2001 From: Maofeng Date: Fri, 31 Jul 2026 10:04:46 +0800 Subject: [PATCH] docs(resident): document timer and TCP drivers Describe ResidentSupervisor ownership, TCP policy and configuration, bounded stream backpressure, timer scheduling, restart behavior, and deterministic Host-resource shutdown order. --- README.md | 6 +++ crates/wasmeld-console/README.md | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/README.md b/README.md index e52386e..bfb4a1a 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ Host driver <- validated operation <- raw effect <- 线程外;协议级驱动以及文件监听、串口、系统信号等其它来源通过独立版本的 WIT 能力演进, 不需要扩大基础 service world。 +Console 已接入 Timer 与 TCP Host Driver:平台配置的 Timer、Listener 和 Stream 在 +Tokio task 中等待,并通过有界队列交给专用 `ResidentSupervisor` 线程串行进入 +`ResidentSession`。TCP 地址执行默认拒绝的 Host policy,字节流支持有界读写、半关闭和 +pause/resume;服务停止、重启和 Runtime Deployment 恢复会按 Revision 创建或释放 Host +资源。UDP 和 Unix Driver 仍待接入。 + ## 结构 ```text diff --git a/crates/wasmeld-console/README.md b/crates/wasmeld-console/README.md index 713a4d9..8ec67cb 100644 --- a/crates/wasmeld-console/README.md +++ b/crates/wasmeld-console/README.md @@ -30,6 +30,71 @@ Host KV 使用 `(service_id, key)` 复合主键存储在该数据库中:同一 编译后的本地机器码默认缓存在 `var/wasmeld/component-cache`,相同 Component 在 Console 或 Runtime 重启后可由 Wasmtime 直接复用;缓存不包含 Actor 内存。 +## 常驻 Host Driver + +导出 `wasmeld:resident/actor@0.1.0` 的 Component 启动时,Console 会为它创建独立的 +`ResidentSupervisor`。Supervisor 在专用阻塞线程上独占 `ResidentSession`,避免同步 +Actor mailbox 阻塞 Tokio executor。Timer、TCP Listener 和每条 TCP Stream 由 Tokio +task 等待外部事件,再通过容量受限的 channel 汇聚到同一个 Supervisor。 + +Host 资源属于平台配置,不由 Component 创建,也不写入 `.wasmpkg`。当前可通过 +`ConsoleConfig::resident_services` 为稳定服务 ID 配置 TCP Listener 和 Timer: + +```rust +use std::collections::BTreeMap; +use wasmeld_console::{ + ConsoleConfig, NetworkScope, ResidentPolicy, ResidentServiceConfig, + ResidentTcpListenerConfig, ResidentTimerConfig, +}; + +let mut resident_services = BTreeMap::new(); +resident_services.insert( + "scheduler".to_owned(), + ResidentServiceConfig { + policy: ResidentPolicy { + tcp_listen: NetworkScope::Loopback, + ..ResidentPolicy::default() + }, + tcp_listeners: vec![ResidentTcpListenerConfig { + name: "internal-api".to_owned(), + bind: "127.0.0.1:9000".parse().unwrap(), + }], + timers: vec![ResidentTimerConfig { + name: "heartbeat".to_owned(), + initial_delay_ms: 1_000, + interval_ms: Some(30_000), + }], + ..ResidentServiceConfig::default() + }, +); +let config = ConsoleConfig { + resident_services, + ..ConsoleConfig::default() +}; +``` + +`ResidentPolicy` 默认拒绝全部网络地址;配置 Listener 时还必须显式选择 `Loopback` +或 `Any`。Listener 在 Actor 启动过程中完成策略校验和 bind,任何失败都会回滚刚启动的 +Actor,避免出现“Actor 正在运行但端口未监听”的半启动状态。Listener、Timer 和其它 +顶层资源名称在同一服务内必须唯一,每个 Revision 都会获得独立的 Host handle 和不复用 +资源 ID。 + +TCP Driver 每次最多读取 `limits.resident.max_stream_chunk_bytes`,不会把 socket handle +交给 Wasm。TCP 字节在 Supervisor 队列满时等待并把背压传递到内核接收缓冲区,不能像 +Timer occurrence 一样丢弃。Component 可通过 WIT 返回 `write-stream`、`close-stream`、 +`pause-stream` 和 `resume-stream`;每条连接的写入/控制队列也是有界的,慢客户端填满 +队列时只关闭该连接,不阻塞同一 Actor 的其它连接。 + +Timer task 只负责等待,队列满时丢弃该次 occurrence,而不是创建无界积压。Component +返回 `arm-timer` 会替换 Host 初始日程,`cancel-timer` 会取消它;generation 使取消前 +已经排队的迟到事件失效。 + +停止顺序固定为:停止接收新 Driver 事件、停止 accept、投递 `shutdown`、关闭 Stream +和 Timer task、先释放子 Stream 再释放 Listener、最后停止 Actor。服务重启和 Runtime +Deployment 恢复都会重新 bind 并创建新 Session,不会复用旧 Revision 的 socket、Timer +或 Component 内存。UDP 和 Unix Driver 尚未接入,后续继续复用相同的 Supervisor +序列化边界。 + ## 启动 `wasmeld-console` 需要 Rust 1.95 或更高版本;Wasm 组件继续使用项目约定的 Rust 1.90