Skip to content

Demo 04:持久计时器

普通 time.sleep() 的问题是:等待状态存在进程内存里。进程重启后,它不知道自己还要等多久,也不知道该继续哪个 workflow。

Durable Timer 的目标是把“未来继续执行”变成持久事实。

Timer 的语义

python
ctx.sleep("settlement-wait", seconds=5)

它不是简单阻塞线程,而是:

  1. 在 Journal 中记录 PENDING_TIMER,包含 fire_at
  2. 当前 attempt 暂停,invocation 进入 WAITING_TIMER
  3. 后台 worker 周期扫描,到期后重新执行 handler。
  4. 重放到 sleep 时发现时间已到,把该 step 标记为完成并继续。

流程图

为什么 timer 也要进 Journal

因为等待本身也是业务执行的一部分。比如:

python
ctx.run("send-email", send_email)
ctx.sleep("wait-user-confirm", seconds=86400)
ctx.run("disable-account", disable_account)

如果 sleep 不持久化,系统重启后可能:

错误后果
忘记等待永远不继续
从头等待额外延迟一天
重新发邮件产生重复通知

Durable Timer 让等待和其他步骤一样可重放。

教学版和 Restate 的差异

Restate 支持 durable sleeps、delayed messages、timeouts,并且在 FaaS 场景可以让函数挂起,避免为长时间等待付计算资源费用。教学版只实现 sleep,并通过后台 loop 扫描恢复。

能力教学版Restate 生产版
sleep支持支持
delayed message不支持支持
promise / awakeable不支持支持
FaaS suspension不支持支持
分区 timer index简化为查询 Journal分区存储索引

小练习

  1. 把 sleep 时间改成 60 秒,重启后端进程,确认 invocation 仍能继续。
  2. 增加一个 cancelled 状态,思考 timer 到期后是否还应继续执行。

Teaching project inspired by Restate's public architecture and documentation.