跳到正文
豫言包管理
← 全部包

豫言操作系统持久独占 0.1.0

豫言 · 库

在持久对象内开启并发独占区:区内可等待外部输入输出,其他事件排队等候。

持久独占接口规范 0.1.0

本包让应用在当前持久对象(Durable Object)里开启一个并发独占区:区内应用可以等待外部输入输出(调用别的服务、读上游、跑较长的计算),而这段时间里发往该对象的其他事件(HTTP 请求、告警、套接字消息)排队等候,不与区内的读写交错。它对应平台的 blockConcurrencyWhile,典型用途是“读—改—外部调用—写”必须整体串行的请求,例如同一站点同一时刻只处理一个动态请求。

模型

当前编译入口仍是 _start,所以独占区通过事件重入实现(与[持久事务](../持久事务/规范.汉语.md)对称):应用在持久对象事件里调用 执行持久独占 操作名 参数,宿主暂停向该对象投递其他事件,重新进入应用,事件种类为 durable-block(应用据[网页入站接口](../网页入站/规范.汉语.md)的 读取入站事件种类 辨别);独占区处理入口用 读取持久独占名、读取持久独占参数 取得本次操作名和参数,做完工作后调用 完成持久独占 结果 设置结果;宿主待处理入口结束后恢复投递,并把结果作为 执行持久独占 的返回值。此重入方式是适配实现,后续可以换成直接调用类型化回调,应用所见的语义不变。

语义

操作名是 1 至 128 字节的文字,由应用约定,用来在独占区处理入口里选择要做的事;参数与结果都是有效 JSON 文字,各不超过 8 MiB,由宿主验证(非法 JSON 使调用失败)。独占区处理入口看不到外层的 HTTP 请求(durable-block 不是 HTTP 事件,不能读请求或设响应),外层需要交给它的请求资料(方法、路径、正文、标头等)应放进参数 JSON,结果再由外层据以构造响应。完成持久独占 每个独占区必须且只能成功调用一次。

区内应用可以读写持久仓(包括[持久事务](../持久事务/规范.汉语.md)的直接访问函数)、启动事务、读写[持久告警](../持久告警/规范.汉语.md)、等待任意外部输入输出;不能再开启独占区(独占区内不可再启动独占区)。多个独占区依次执行,不会重叠;独占区进行期间到达的其他事件在区结束后才被投递。独占区期间该对象的吞吐被完全占用,因此区内的耗时越短越好。

区内失败——处理入口抛出未捕获异常、没有调用 完成持久独占、结果不是有效 JSON 或超过 8 MiB、超过事件时限——不会传给平台:宿主把失败作为返回值交给外层,执行持久独占 抛出可用「尝试运行」捕获的豫言异常,消息以 持久独占失败: 开头并保留原因文字;对象不会被重置。这是有意的设计:平台原生的 blockConcurrencyWhile 回调一旦抛错就会重置整个持久对象(丢弃内存状态、使正在进行的请求失败,本地 workerd 已验),而应用里的独占区失败是常见的业务情形。处理入口自己抛出而未捕获的豫言异常在宿主边界表现为 RuntimeError: illegal cast,宿主会在消息后附上说明;需要向外层报告具体原因时,处理入口应自己用「尝试运行」捕获,并把原因写进 完成持久独占 的结果。

平台在独占区回调超过 30 秒时重置对象(本地 workerd 已验:超过 30 秒后对象被重置,请求失败)。为使超时表现为可捕获的异常而不是重置,宿主把 durable-block 事件的默认墙钟时限设为 25 秒,可通过构建产物的 执行配置.json 调整但不得超过 30 秒;时限只在豫言调用宿主能力时检查,单次外部调用本身耗时过长仍可能触及平台的 30 秒线,应用应给外部调用设置更短的超时。

函数

执行持久独占 操作名 参数:返回结果 JSON 文字。读取持久独占名:无参,返回操作名。读取持久独占参数:无参,返回与调用者传入一致的参数文字。完成持久独占 结果:设置结果,返回有。

失败情形

| 情形 | 类别 | | --- | --- | | 操作名不是 1 至 128 字节;参数不是有效 JSON 或超过 8 MiB | 违规:执行持久独占 抛可捕获异常,消息 持久独占失败:… | | 处理入口失败、缺结果、超时 | 抛可捕获异常,消息 持久独占失败:…,对象不重置 | | 完成持久独占 的结果不是有效 JSON、超过 8 MiB,或重复调用 | 在独占区内由 完成持久独占 抛可捕获异常(持久独占结果无效:…),处理入口可捕获后另给结果 | | 在非持久对象事件、事务入口内、独占区内调用 执行持久独占;在独占区外调用 读取持久独占名、读取持久独占参数、完成持久独占 | 违规:抛可捕获的豫言异常 | | 交换文字超过宿主上限(16 MiB)、平台故障、独占区超过平台的 30 秒 | 平台或宿主故障:中止当前事件(超过 30 秒时对象被重置),豫言无法捕获 |

跨宿主一致性

任何实现须保持:区内不与其他事件交错、区内到达的事件区后才投递;区内失败以可捕获异常报告且不重置对象;不可嵌套;参数结果按 JSON 文字原样传递(结果不必与 完成持久独占 的文字字节相同,但 JSON 意义相等);上述限额与失败类别。

一致性样例

对象里键 n 初为 0。五个并发请求各自 执行持久独占 "counter" 参数,处理入口读 n、等待外部 30 毫秒、写回 n+1 并返回新值,则五个结果恰为 1 至 5 的一个排列,最终 n 为 5,外部等待的区间两两不重叠;同样的读—等—写若不放进独占区,五个并发请求的结果会都是 1、最终 n 为 1(更新丢失)。独占区进行中到达的 durable-fetch 请求在区结束之后才被处理。执行持久独占 "fail" "{}" 而处理入口未捕获异常时,抛出以 持久独占失败: 开头的异常,其后对象照常服务且实例不变。执行持久独占 "" "{}"、执行持久独占 "x" "不是JSON" 抛异常。区内再 执行持久独占 抛出 独占区内不可再启动独占区。

边界

本包不提供带优先级的队列、超时后自动放弃的独占区、跨对象的分布式锁,也不把外层 HTTP 请求带进区内。它只用于已授权的当前持久对象,对象的名称与授权由宿主和部署配置决定。独占区不改变平台对存储读写的输入门规则,只是在区内额外挡住其他事件的投递。

依赖

查看包配置

上传历史

当前上传修订:1 ·

  1. 上传修订 1
    下载 ZIP

包层级

父包:豫言操作系统接口

没有子包。