Cloudflare Workflow 实例出错后怎么从中间重启?

一个实例走到第三步出错,进入了 errored。你修好了代码,总不能让用户重新下一次单。

用 restart({ from: { name: "步骤名" } }):它从指定步骤重启,复用更早步骤的缓存结果,目标步骤及之后的步骤重新执行。 不带参数的 restart() 则是从头开始,官方说明它会清掉中间状态,所有步骤重新执行。

这两种行为我都在本地验证过,而且发现了一个容易忽略的细节:从中间重启复用的是缓存。下面先讲实例有哪些状态和方法,再讲这个坑。

一个实例会经历哪些状态?

官方文档列出的实例状态包括 queued、running、waiting、paused、errored、terminated、complete 等。

创建后先排队,开始执行变为 running;遇到 step.sleep、重试等待或 waitForEvent 时变为 waiting,此时不占并发名额;步骤重试耗尽且未被捕获则 errored。

实例句柄能做哪些操作?

实例句柄提供 status()、pause()、resume()、terminate()、restart() 等运维方法。出错时最常用的是 status() 看状态和错误,再用 restart() 恢复。

restart 带参数和不带参数差在哪?

我在本地用三个步骤 a、b、c 试过:

  • 从 c 步骤重启,a、b 没有再执行。
  • 不带参数重启,a 重新执行。

同时还能看到另一件事:写在步骤外的代码(我例子里的一条日志)在重启后又执行了一次,所以步骤外不能放副作用,原因见 写 Workflows 要遵守哪些规则。

排错流程因此很顺畅:定位出错步骤,修复代码,从该步骤重启,而不必让用户重新下单。

改了已完成步骤的逻辑,重启后会生效吗?

不会,除非从该步骤重启。从中间重启复用的是缓存,已完成的步骤只要在目标步骤之前,就不会重新执行。

所以如果你修的是一个已经成功的步骤,要从它那里重启,而不是从后面出错的那一步。

同一个订单能重新创建一个实例吗?

通常不行。实例 ID 在保留期内不能复用,create 遇到重复 ID 会抛错,本地我看到的错误是 instance.already_exists。

这是好事:用业务上稳定的 ID,比如 order-<orderId>,同一订单就只会有一个流程。需要重新跑,就重启已有实例,而不是再建一个。若一个业务对象确实需要多次流程,ID 里加上流程类型或序号。

状态、步骤与重试的整体模型,见 Workflows 怎么让长流程不从头再来。

restart() 带参数与不带参数的行为、步骤外代码在重启后重复执行、重复 ID 抛 instance.already_exists,是我在本地 wrangler dev 上跑过的。实例状态列表、各运维方法与其说明、restart() 不带参数会清掉中间状态,只是官方文档的说法,线上行为我没有验证。行为会变化,以官方文档为准。官方参考:Workers API。