消息队列接口规范 0.1.0
本包让应用向获授权的消息队列投递 JSON 消息,并在队列事件里读取当前批次、逐条确认或延后重试。生产者与消费者共用一个包。队列事件里,应用据[网页入站接口](../网页入站/规范.汉语.md)的 读取入站事件种类 返回 queue 选择自己的消费入口;每一批消息对应一次事件、一个新的程序实例,程序内存不跨事件保留,需要跨批次的状态应存进持久仓或关系库。
生产者
发送队列消息 的参数依次是队列绑定名、消息体 JSON 文字和延迟秒数,投递一条消息。绑定名由宿主许可(例如 {"QUEUE":["PAGE_QUEUE"]})核对:未授权或当前部署没有配置的名称是部署错误,宿主直接中止当前请求,空名称则由本包抛出豫言异常。消息体可以是任意 JSON 值(对象、数组、字符串、数字、布尔、null),本包让宿主先解析再规范化:去掉冗余空白、统一转义,数字按 IEEE 754 双精度取值(与 JS 一致,绝对值超过 2^53−1 的整数会失去精度,应改用字符串)。输入文字与规范化后的文字都不得超过 128 KB,即 128000 个 UTF-8 字节(平台按十进制千字节计,本地 workerd 实测恰 128000 字节可投、128001 字节被拒),嵌套不得超过 24 层(数组或对象各算一层);平台文档称上限含元数据,接近上限的消息若仍被平台拒绝,按平台失败处理。消息体里不得出现不属于 JSON 的值或宿主专用记号(形如 {"$句柄":…}、{"$未定义":…}、{"$大整数":…}、{"$数字":…} 的对象,包括借 \u0024 之类转义拼出的键,以及 1e999 之类变成无穷大的数字),否则抛出异常:这些记号在宿主桥里表示宿主对象,不允许应用借消息体伪造。延迟秒数须在 0 至 43200(12 小时)之间,0 表示不延迟,负数或超限抛出异常。消息按 JSON 内容类型存入队列,消费者读到的正是同一个 JSON 值。
批量发送队列消息 的参数依次是队列绑定名和 JSON 数组文字,每项是 {"body":任意 JSON 值,"delaySeconds":0 至 43200 的整数},delaySeconds 可省,项里不许有别的字段。数组有 1 至 100 项,每条 body 不超过 128000 字节,全部 body 合计不超过 256000 字节,数组文字不超过 1 MiB,嵌套限制同上。本包在豫言里完整校验整个数组后才调用平台,任一项不合格则一条也不投递;平台拒绝整批时是否有部分消息已入队由平台决定,应用需要幂等时自行保证。
生产者的两个函数都以异常报告失败,不返回状态:违规、超限、不是 JSON、含宿主记号、延迟越界都在调用平台之前抛出豫言异常,异常消息是固定的中文说明(例如 消息体不是有效的 JSON 文字、消息体超过 128000 字节、延迟秒数须在 0 至 43200 之间、批量消息不得超过 100 条);平台拒绝时抛出的异常消息是 队列发送失败: 或 队列批量发送失败: 加上平台报告的原文。应用可用「尝试运行」捕获这些异常。
消费者
消费者的三个函数只在当前事件是队列事件时可用,其他事件里调用会抛出可捕获的豫言异常 当前事件不是队列事件;它们只在这次事件内有效。读取队列批次 返回当前批次的 JSON 文字:{"queue":"队列名","messages":[{"id":"消息标识","attempts":投递次数,"timestamp":入队时刻的Unix毫秒,"body":JSON 值},…]}。messages 的顺序就是确认与重试所用的序号顺序,序号从 0 起;attempts 从 1 起,每次重新投递加 1;timestamp 是整数毫秒。body 必须是 JSON 值:若平台上的消息体不是(例如生产者用结构化克隆发送了 Date、Map、Set、二进制、undefined、BigInt、NaN 或无穷大),读取队列批次 抛出异常 队列消息正文不是 JSON 值:序号 n。嵌套超过宿主桥限制(32 层)的消息体会使宿主中止本次事件。
确认队列消息 显式确认第 n 条消息(从 0 起),表示这条消息已处理完毕,本次事件里不会再重试它。重试队列消息 请求重新投递第 n 条消息;第二个参数是延迟秒数,0 表示使用平台的默认延迟,否则须在 1 至 43200 之间。序号小于 0 或不小于本批消息数、延迟越界,都抛出可捕获的豫言异常(队列消息序号越界、延迟秒数须在 0 至 43200 之间)。对同一条消息重复确认、重试或先确认后重试,效果以平台为准,应用应避免。
事件的结果沿用平台语义:程序正常结束、对某条消息没有显式重试的,视为成功,不需要逐条确认;豫言异常无人捕获时,宿主不吞掉异常,本次队列处理失败,平台按队列的重试与死信配置整批重新投递(attempts 相应加一)。已显式确认的消息是否随整批重投由平台决定:Cloudflare 文档承诺不重投,但本地 Miniflare 模拟器实测会连同已确认者一起整批重投;应用不应依赖任何一方,消费处理必须幂等。单个事件另有宿主设定的运行时限。本包不提供整批确认或整批重试,需要时对每条消息调用一次。
一致性样例
| 情境 | 必须观察到 |
| --- | --- |
| 投递 {"kind":"page","url":"/release/x","version":"v8","refresh":true},延迟 0 | 平台 send 收到同一个对象,选项恰为 {"contentType":"json"} |
| 延迟 30、43200 / -1、43201 | 前者选项含 delaySeconds;后者抛出异常且平台未被调用 |
| 消息体 {"$句柄":"1"}、{"\u0024句柄":"1"}、1e999、{ | 均抛出异常,平台未被调用 |
| 消息体恰 128000 字节 / 多一字节 | 前者成功,后者抛出 消息体超过 128000 字节 |
| 批量 1 项与 100 项 / 0 项与 101 项 | 前者成功;后者抛出异常,一条也未投递 |
| 批量项含 contentType 字段、缺 body、delaySeconds 为 1.5 | 均抛出异常,一条也未投递 |
| body 里含 ],[、{"body":1}、引号与反斜线的字符串 | 每条 body 逐字节还原,不被误拆 |
| 平台拒绝,消息为 Queue is full | 异常消息为 队列发送失败:Queue is full |
| 队列事件里读取含三条消息的批次 | 顺序、id、attempts、毫秒 timestamp 与 body 与平台一致;此时没有任何消息被确认或重试 |
| 依次确认 0、延后重试 1(30 秒)、不处理 2 | 平台收到 ack、retry({delaySeconds:30}),第三条无调用 |
| 确认序号等于消息数或 -1;重试延迟 -1 或 43201 | 均抛出可捕获异常,平台未收到相应调用 |
| 队列事件里程序抛出未捕获异常 | 宿主把失败交还平台(不吞异常),平台整批重投,attempts 加一 |
| 普通 HTTP 请求里调用消费函数 | 抛出可捕获异常 当前事件不是队列事件 |
边界
本包不提供 ackAll、retryAll、队列指标、队列与消费者的创建及配置(批大小、重试次数、死信队列属于部署)、消息去重、顺序保证或跨队列事务;只发送和接收 JSON 值,不发送文字或二进制内容类型,也不读取消息的内容类型。云工适配把生产者映射到 Queue 绑定的 send 与 sendBatch,把消费者映射到 queue 事件的 MessageBatch;其他平台可以用等价的队列实现,只要 JSON 值语义、限额和确认重试语义一致。