消息队列云工适配
生产者用云工 QUEUE 绑定的 send 与 sendBatch,消费者用 queue 事件的 MessageBatch(云工宿主已把批次和消息对象放进句柄表,ack、retry({delaySeconds}) 逐条调用)。适配的要点:
- 消息体经宿主规范化:豫言把消息体文字作为字符串交给宿主的
JSON.parse,取回JSON.stringify的规范文字,再直接放进send的参数文字;字符串字面量由宿主的TextDecoder生成,所以任意控制字符都不会出错,也不依赖豫言 JSON 库对转义的支持。规范文字里不许出现{"$句柄":、{"$未定义":、{"$大整数":、{"$数字":开头的对象:句柄桥会把它们还原成宿主对象或特殊值,允许的话应用可借消息体伪造宿主句柄。宿主规范文字里字符串内的引号都带反斜线,所以这一子串检查既不漏报也不误伤字符串内容。 - 批量数组由豫言拆分:适配只在规范文字上做一遍带字符串与转义状态的括号扫描,拆出每项与其
body文字,逐项验证形状与限额后重新拼成{"body":…,"contentType":"json","delaySeconds":…}。body始终是不透明的规范文字,不经豫言 JSON 库解析,所以\r、\uXXXX、负数、指数等都不受当前 JSON 库限制。 - 消费侧读取:批次名、消息数、标识、尝试数用云工宿主原有的队列原语;时间戳通过消息句柄读
timestamp,Date用getTime()取毫秒(测试替身也可直接给毫秒整数);body是宿主输出的规范 JSON,含句柄桥记号(Date、Map、二进制、undefined、BigInt、NaN 等)时抛出豫言异常。标识与队列名的字面量:纯可见 ASCII 直接加引号,其他字符经宿主的TextDecoder与JSON.stringify生成。 - 越界与延迟由适配先核对:宿主对越界序号抛的是宿主 JS 错误,豫言捕获不到,所以先用消息数核对再调用,把越界变成可捕获的豫言异常;宿主原语的
retry({delaySeconds})只在延迟大于 0 时使用。 - 适配不使用
ackAll、retryAll,也不接触消息的内容类型。生产投递固定contentType: "json"。 - 真实本地 workerd(Wrangler 4.129.0)实测:
send/sendBatch以contentType: "json"投递,消费者读到attempts从 1 递增、timestamp为 Date、body为同一 JSON 值;retry({delaySeconds})按延迟重投;单条消息体恰 128000 字节可投、128001 字节被拒(错误文字只是Unknown Internal Error (15000),所以适配自己按 128000 字节校验并给出中文原因);sendBatch里每条同样以 128000 字节为限(两条各 128000 字节共 256000 字节的批量可投);不显式确认也不重试即视为成功;未捕获异常使整批重投,连已显式确认者一并重投(Miniflare 的 broker 在处理失败时不区分已确认消息),所以消费处理必须幂等。 - 单个事件的运行时限(30 秒)和 Wasm 实例不跨事件由云工宿主提供;宿主对
queue事件返回的 Promise 在程序结束时完成,程序抛出未捕获异常则被拒绝,平台据此重试整批。
一致性验证/ 里有试验应用、真实 Wasm 的 Node 测试(含批量拆分的随机结构对拍)和复跑说明。