Durable Taskの価値は、あらゆるバックグラウンドワーカー、メッセージキュー、データベースを置き換えることではなく、長時間にわたる処理、外部イベントを待って停止する処理、または一部のステップを実行した後に中断される可能性がある処理を整理することにあります。.NETブログでは、Durable Task .NET SDKバージョン1.26.0とDurable Task Schedulerを使用した5つの実践例を紹介し、このツールが調整の履歴を保存するものであり、停止したCLR実行スタックを復元するものではないことを強調しています。
中心となる考え方は、ワークフローエンジンが調整するものと、アプリケーションの責任として残るものを分離することです。Durable Taskは進行状況のチェックポイントを保存し、実行スレッドを占有せずに待機し、記録された結果に基づいてオーケストレーターのコードを再実行できます。しかし、ユーザー権限を決定したり、外部副作用が一度だけ実行されることを保証したり、安全に削除できるリソースを判断したり、決済が実際に到達したかどうかを単独で判定したりすることはありません。
人間による承認はワーカーの停止を意味しない
請求書処理では、各請求書を独立したサブオーケストレーション内で実行できます。レビューが不要な請求書は処理を続行し、人間による承認が必要な請求書は、外部イベントと堅牢なタイムアウトを待機します。ワーカーが停止した場合でも、別のワーカーがオーケストレーターを再実行し、状態を手動で再構築することなく待機ポイントに戻ることができます。
ただし、承認イベントは単なるシグナルです。認証済みのエンドポイントは、シグナルを送信する前に最終決定をアプリケーションストアへアトミックに記録する必要があり、会計ステップは固定されたデプロイIDと変更不可能なリクエストフィンガープリントを検証する必要があります。会計エントリが受け入れられた後にアクティビティの確認が失われた場合、Durable Taskの履歴だけでは重複を防ぐのに十分ではなく、会計システムとのリコンシリエーションプロトコルが必要になります。
Azure環境のプロビジョニング:ARMの役割はどこまでか
この記事では、ARMとBicepが特定のリソースのデプロイには十分な場合があると説明しています。これらは依存関係の順序付け、並列実行、固定されたIDによる望ましい状態の再適用を提供します。そのため、ARMがすでに提供しているデプロイ計画を再構築するためにDurable Taskを追加する価値はありません。
メリットが現れるのは、フローがリソースのデプロイを超えて、テナントのリクエストを受け付け、進捗を通知し、準備完了を待機してからテナントを有効化する場合です。この例では、プロビジョニングリクエストとその識別子をoutboxとともにアプリケーションデータベースへ保存し、ネットワーク、データベース、ストレージ、アプリケーション、DNS、準備状況チェックの各段階を結び付けるオーケストレーションを使用します。一方、Azure自体の操作には、依然として操作ログ、固定されたID、応答を失った場合のリコンシリエーションが必要です。
また、この記事では補償処理を取り消しボタンと見なさないよう警告しています。ストレージの失敗後も、Azureがデータベースを作成中である可能性があります。そのため、古い試行が新しい操作を開始しないようにし、過去に送信された操作を確認し、遅延した操作がリソースを再作成する可能性がないことを確認した後でのみ、その試行だけが所有するリソースを削除する必要があります。状態または所有権を証明できない場合、安全な結果は推測による削除ではなくNeedsInterventionです。
決済のタイムアウトは拒否ではない
サブスクリプションのライフサイクルでは、処理が受け入れられた後に決済プロバイダーからの応答が消えることがあります。直ちに再試行すると二重請求が発生する可能性があり、拒否と見なすと誤解を招く通知を送信する可能性があります。この例では、各決済サイクルをサイクルIDと固定された決済キーに関連付け、durableタイマー、コールバック、定期チェック、明確な猶予期間を使用します。
決済台帳が、Unknown、Pending、Declined、Paid、NotChargedの状態におけるauthoritativeな参照元であり続けます。領収書の確認と現在のサイクルの終了が完了するまで、次のサイクルには移行しません。タイムアウトになっても状態が未確定のままである場合、決済の成功または失敗を推測するのではなく、結果はNeedsReconciliationになります。
遅延イベントには宛先側の保護が必要
ニュース記事の検索インデックスを更新する場合、バージョン12がバージョン13の後に到着したり、インデックス処理が逆の順序で完了したりすることがあります。durableエンティティは、確認した最大バージョンとカウンター更新の順序を保存できますが、外部インデックスをロックしたり、2つのリクエストが並行して書き込むことを防いだりはしません。
そのため、宛先自体がアトミックなバージョンバリアを適用し、新しいバージョンが確定した後に古いバージョンが書き込まれることを拒否する必要があります。また、システムには信頼できるinbox、フォローアップ用のディスパッチャー、ソースとの定期的なリコンシリエーションも必要です。単一のIDを持つオーケストレーターのパターンであっても、外部副作用の単一実行を保証するものではありません。
AIエージェントにとって何を意味するのか
インシデントアシスタントのワークフローでは、処理中に特定されたモデルの提案を保存し、エンジニアによる承認を待ち、その後、停止の可能性があっても承認済みのツールを実行する必要があります。ここでの価値は、再実行のたびに新しい提案を再生成することではなく、承認の経路と同じ決定を復元することにあります。提案のID、ツールの有効性、古いリクエストや重複したリクエストの実行防止は、引き続きアプリケーションの責任です。
5つの例から得られる実践的な結論は、「次に何が起こるか」を保存すること自体がシステムになる場合に、Durable Taskが適しているということです。一方、アプリケーションがすでにキュー、タイマー、明確なリコンシリエーションログを備えている場合、またはARMのように外部システムが信頼できる調整機能を提供している場合、フレームワークは価値以上の複雑性を追加する可能性があります。また、すべての例は、権威ある記録、idempotencyキー、バージョンバリア、outbox、またはリコンシリエーションプロトコルといった明示的な外部境界に依存しています。