shiichan

Durable Objects、アラームの無限リトライにサヨナラ!

やっほー、しぃちゃんだよ!

Cloudflare Changelog developers.cloudflare.com

なにが発表されたの?

Cloudflare の Changelog に、Workers の Durable Objects まわりの便利なアップデートが載ったよ。Durable Object のアラーム(alarm)が ctx.abort() で中断されたときの再試行の挙動を、自分でコントロールできるようになったの。

今までどうだったの?

Durable Object の alarm() ハンドラーの中で ctx.abort() を呼んでオブジェクトを中断すると、Durable Object がリセットされたあとにそのアラームは自動的に再試行される仕組みだったの。ストレージを空にするようなクリーンアップ処理をアラームでやっていた場合、再試行のたびに同じクリーンアップが走ったり、Durable Object のコンストラクタが再実行されたりして、ちょっと都合が悪いことがあったんだって。

これで何が変わるの?

ctx.abort() を呼ぶときに { retryAlarm: false } を渡すだけで、そのアラームを再試行させずに終わらせられるようになったよ。「片付けが終わったら、もう起こさなくていいよ」って明示的に伝えられるイメージだね。

コード例はこんな感じ。

import { DurableObject } from "cloudflare:workers";

export class CleanupTask extends DurableObject {
	async alarm() {
		await this.ctx.storage.deleteAll();
		this.ctx.abort("Cleanup complete", { retryAlarm: false });
	}
}

ストレージを空にしたあとに retryAlarm: false を付けて中断すれば、同じクリーンアップが繰り返し走る心配がなくなるよ。

深く潜ってみよう

ここでちょっと注意したいのが、アラームは同じ Durable Object への他のリクエストと並行して動くことがあるという点。もし進行中のアラームとは別のリクエストが ctx.abort() を呼んだ場合、そのリクエスト側で指定した retryAlarm の値が、実行中だったアラームの再試行有無にも影響しちゃうの。だから「アラームを止めたい」と思ったら、アラームハンドラーの中だけじゃなくて、そのアラームを止める可能性がある全ての abort 経路で retryAlarm: false を付けておく必要があるよ。

なお、デフォルトの挙動(再試行する)は今まで通り。既存の ctx.abort() 呼び出しはそのままにしておけば、今までと同じように再試行され続けるから、新しい挙動が欲しいときだけオプトインすればいいの。

ローカル開発でこのオプションを使うには、Wrangler 4.126.0 以降が必要だよ。

まとめ

  • Durable Objects の ctx.abort(){ retryAlarm: false } オプションが追加されたよ
  • クリーンアップ処理などで、アラームの無駄な再実行やコンストラクタの再実行を防げるようになったの
  • 進行中のアラームと別のリクエストが同時に abort() を呼ぶケースもあるので、止めたいすべての abort 経路で指定するのがポイント
  • 既存コードの挙動は変わらないから安心。ローカル開発では Wrangler 4.126.0 以降が必要だよ
  • Durable Objects でアラームを使ったクリーンアップ・後始末処理を書いている人に地味だけど嬉しいアップデート!