shiichan

Workflows に saga ロールバックがやってきた!

やっほー、しぃちゃんだよ!今日は Cloudflare の Workflows がちょっと賢くなったニュースを持ってきたよ。処理が途中でコケたときの「お片付け」が、ぐっと書きやすくなるお話なの。

Cloudflare Changelog developers.cloudflare.com

なにが発表されたの?

Workflows に saga スタイルの ロールバック(巻き戻し)機能が追加されたよ。これは Cloudflare の Changelog で発表されたの。各 step.do() に「補償ロジック(compensating logic)」をくっつけておけて、インスタンスが途中で失敗したら、そのロールバック処理が ステップ開始とは逆順 に実行されるんだよ。

今までどうだったの?

これまでは、複数ステップの処理が途中でコケたときのお片付けを、いちばん外側の catch ブロックに全部まとめて書くことが多かったの。在庫の確保、決済の承認、チケットの発行、インフラのプロビジョニングみたいに外部システムをまたぐ処理だと、「どのステップの何を取り消すんだっけ?」って catch の中がごちゃごちゃになりがちだったんだよね。

これで何が変わるの?

これからは、取り消したいステップの すぐ隣 に、その巻き戻し処理を置けるようになるの。決済を承認したステップのそばに「決済を取り消す」処理、リソースを作ったステップのそばに「リソースを消す」処理、っていう感じ。お片付けのコードが散らからないから、あとから読む人にもやさしいよ。

深く潜ってみよう

使い方はシンプルで、step.do() のオプションに rollback ハンドラを渡すだけ。しかも巻き戻し処理には 専用のリトライとタイムアウト を設定できるの。

await step.do(
  "provision resource",
  async () => {
    const resource = await provisionResource();
    return { resourceId: resource.id };
  },
  {
    rollback: async ({ output }) => {
      const { resourceId } = output;
      await deleteResource(resourceId);
    },
    rollbackConfig: {
      retries: { limit: 3, delay: "15 seconds", backoff: "linear" },
      timeout: "2 minutes",
    },
  },
);

rollbackConfig でリトライ回数・間隔・バックオフやタイムアウトを、通常のステップとは別に決められるのがポイントだよ。さらにロールバックの結果はインスタンスのステータスに表示されて、ロールバックのライフサイクルイベントが分析(analytics)にも出るようになったの。これのおかげで、本番のデバッグで「前向きの処理が失敗したのか、巻き戻しの方が失敗したのか」を見分けやすくなるんだ。設定できる項目は rollback options にまとまっているよ。

まとめ

  • Workflows に saga スタイルの ロールバック が追加されたよ(Cloudflare の Changelog 発表)
  • step.do()rollback ハンドラを付けると、失敗時に 逆順 で巻き戻しが走るの
  • ロールバックには専用の rollbackConfig(リトライ・タイムアウト)を設定できる
  • 結果はインスタンスのステータスに出て、ライフサイクルイベントで前向き失敗と巻き戻し失敗を区別できる

決済やインフラのプロビジョニングみたいに、途中で失敗すると困る多段処理を Workflows で書いている人にぴったりの機能だよ!