workflow-orchestration-patterns について
workflow-orchestration-patternsは、Temporalで信頼性の高い分散ワークフローを設計するためのスキルです。ワークフローとアクティビティの境界、決定性、復旧、再試行に加え、Sagaや並列実行のパターンを扱います。
主な機能
- 01オーケストレーションと外部アクティビティの分離
- 02Sagaの補償フロー設計
- 03長期実行するエンティティワークフローのモデル化
- 04並列タスクとコールバックの調整
- 05決定性、再試行、冪等性の適用
活用シーン
- 01複数段階の業務プロセスの調整
- 02障害後のワークフロー復旧
- 03補償処理を伴う分散トランザクションの実装
- 04人による承認や外部コールバックの待機
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hermeticormus/ libreuiux-claude-code --skill workflow-orchestration-patternsインストール後、Claude Code で/workflow-orchestration-patternsを入力して読み込まれたか確認します。
詳細
ワークフローオーケストレーションのパターン
Temporal を使ったワークフローオーケストレーションのアーキテクチャを習得し、信頼性の高い分散システムの構築に必要な基本的な設計上の判断、レジリエンスのパターン、ベストプラクティスを学びます。
ワークフローオーケストレーションを使用する場面
理想的なユースケース(出典:docs.temporal.io)
- 複数ステップのプロセス:マシン/サービス/データベースにまたがるプロセス
- 分散トランザクション:全か無かのセマンティクスが必要なもの
- 長時間実行されるワークフロー:状態を自動的に永続化し、数時間から数年間実行されるもの
- 障害復旧:最後に成功したステップから再開する必要があるもの
- ビジネスプロセス:予約、注文、キャンペーン、承認
- エンティティのライフサイクル管理:在庫追跡、アカウント管理、カートのワークフロー
- インフラストラクチャの自動化:CI/CD パイプライン、プロビジョニング、デプロイ
- ヒューマン・イン・ザ・ループ:タイムアウトとエスカレーションが必要なシステム
使用すべきでない場面
- 単純な CRUD 操作(直接 API 呼び出しを使用)
- 純粋なデータ処理パイプライン(Airflow やバッチ処理を使用)
- ステートレスなリクエスト/レスポンス(標準的な API を使用)
- リアルタイムストリーミング(Kafka やイベントプロセッサーを使用)
重要な設計上の判断:ワークフローとアクティビティ
基本ルール(出典:temporal.io/blog/workflow-engine-principles):
- ワークフロー=オーケストレーションロジックと意思決定
- アクティビティ=外部とのやり取り(API、データベース、ネットワーク呼び出し)
ワークフロー(オーケストレーション)
特徴:
- ビジネスロジックと連携処理を含む
- 決定論的でなければなりません(同じ入力 → 同じ出力)
- 外部への直接呼び出しはできません
- 障害発生時にも状態が自動的に保持される
- インフラストラクチャ障害が発生しても、数年間実行できます
ワークフロータスクの例:
- 実行するステップを決定する
- 補償ロジックを処理する
- タイムアウトと再試行を管理する
- 子ワークフローを調整する
アクティビティ(外部とのやり取り)
特徴:
- 外部システムとのやり取りをすべて処理する
- 非決定的な処理(API 呼び出し、DB 書き込み)が可能
- タイムアウトと再試行のロジックが組み込まれている
- 冪等でなければなりません(N 回呼び出しても 1 回呼び出した場合と同じ)
- 短時間で完了する(通常は数秒から数分)
アクティビティタスクの例:
- 決済ゲートウェイ API を呼び出す
- データベースに書き込む
- メールや通知を送信する
- 外部サービスにクエリを送信する
設計判断のフレームワーク
Does it touch external systems? → Activity
Is it orchestration/decision logic? → Workflow
ワークフローの基本パターン
1. 補償処理を伴う Saga パターン
目的:ロールバック機能を備えた分散トランザクションを実装する
パターン(出典:temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):
For each step:
1. Register compensation BEFORE executing
2. Execute the step (via activity)
3. On failure, run all compensations in reverse order (LIFO)
例:決済ワークフロー
- 在庫を確保する(補償処理:在庫を解放する)
- 決済を請求する(補償処理:決済を返金する)
- 注文を履行する(補償処理:履行をキャンセルする)
重要な要件:
- 補償処理は冪等でなければなりません
- ステップの実行前に補償処理を登録します
- 補償処理は逆順に実行します
- 部分的な障害を適切に処理します
2. エンティティワークフロー(アクターモデル)
目的:単一のエンティティインスタンスを表す長期間存続するワークフロー
パターン(出典:docs.temporal.io/evaluate/use-cases-design-patterns):
- 1 つのワークフロー実行が 1 つのエンティティ(カート、アカウント、在庫アイテム)に対応します
- ワークフローはエンティティの存続期間中、状態を保持します
- 状態変更のシグナルを受け取ります
- 現在の状態をクエリできます
ユースケースの例:
- ショッピングカート(商品追加、チェックアウト、有効期限切れ)
- 銀行口座(預け入れ、引き出し、残高照会)
- 商品在庫(在庫数の更新、引き当て)
メリット:
- エンティティの振る舞いをカプセル化する
- エンティティごとの一貫性を保証する
- イベントソーシングに自然に適合する
3. ファンアウト/ファンイン(並列実行)
目的:複数のタスクを並列実行し、結果を集約します
パターン:
- 子ワークフローまたは並列アクティビティを起動します
- すべての完了を待ちます
- 結果を集約します
- 部分的な失敗に対処します
スケーリングのルール(出典:temporal.io/blog/workflow-engine-principles):
- 個々のワークフローはスケールさせません
- 100 万件のタスクの場合:1,000 個の子ワークフローを起動し、それぞれで 1,000 件のタスクを実行します
- 各ワークフローの処理範囲を限定します
4. 非同期コールバックパターン
目的:外部イベントまたは人間による承認を待ちます
パターン:
- ワークフローがリクエストを送信してシグナルを待ちます
- 外部システムが非同期で処理します
- シグナルを送信してワークフローを再開します
- ワークフローが応答を受けて処理を続行します
ユースケース:
- 人間による承認ワークフロー
- Webhook コールバック
- 長時間実行される外部プロセス
状態管理と決定性
自動的な状態の保持
Temporal の仕組み(出典:docs.temporal.io/workflows):
- プログラムの状態全体が自動的に保持されます
- イベント履歴にすべてのコマンドとイベントが記録されます
- クラッシュからシームレスに復旧します
- アプリケーションが障害発生前の状態を復元します
決定性に関する制約
ワークフローはステートマシンとして実行されます:
- リプレイ時の動作は一貫している必要があります
- 同じ入力 → 毎回同一の出力
ワークフローで禁止されていること(出典:docs.temporal.io/workflows):
- ❌ スレッド処理、ロック、同期プリミティブ
- ❌ 乱数の生成(
random()) - ❌ グローバル状態または静的変数
- ❌ システム時刻(
datetime.now()) - ❌ 直接的なファイル I/O またはネットワーク呼び出し
- ❌ 非決定的なライブラリ
ワークフローで許可されていること:
- ✅
workflow.now()(決定論的な時刻) - ✅
workflow.random()(決定論的な乱数) - ✅ 純粋関数と計算
- ✅ アクティビティの呼び出し(非決定的な操作)
バージョニング戦略
課題:古い実行がまだ進行中の状態でワークフローのコードを変更すること
解決策:
- バージョニング API:安全な変更のために
workflow.get_version()を使用します - 新しいワークフロータイプ:新しいワークフローを作成し、新しい実行をそこにルーティングします
- 後方互換性:古いイベントが正しくリプレイされることを確認します
レジリエンスとエラー処理
リトライポリシー
デフォルトの動作:Temporal はアクティビティを無期限にリトライします
リトライの設定:
- 初回リトライの間隔
- バックオフ係数(指数バックオフ)
- 最大間隔(リトライの遅延上限)
- 最大試行回数(上限に達すると失敗)
リトライ対象外のエラー:
- 無効な入力(検証エラー)
- ビジネスルール違反
- 恒久的な障害(リソースが見つからない)
冪等性の要件
重要な理由(出典:docs.temporal.io/activities):
- アクティビティは複数回実行される可能性があります
- ネットワーク障害によってリトライが発生します
- 重複実行しても安全でなければなりません
実装戦略:
- 冪等性キー(重複排除)
- 一意制約を使った確認後の処理
- insert の代わりに upsert 操作を使用
- 処理済みのリクエスト ID を追跡
アクティビティのハートビート
目的:長時間実行されるアクティビティの停滞を検出します
パターン:
- アクティビティが定期的にハートビートを送信します
- 進捗情報を含めます
- ハートビートを受信できない場合はタイムアウトします
- 進捗に基づくリトライが可能になります
ベストプラクティス
ワークフローの設計
- ワークフローの役割を明確にする - ワークフローごとに単一の責務を持たせます
- 小さなワークフローにする - スケーラビリティのために子ワークフローを使用します
- 境界を明確にする - ワークフローはオーケストレーションを行い、アクティビティは実行を担います
- ローカルでテストする - 時間をスキップできるテスト環境を使用します
アクティビティの設計
- 冪等な操作 - 安全にリトライできるようにします
- 短時間で完了させる - 時間ではなく、数秒から数分で完了させます
- タイムアウトを設定する - 必ずタイムアウトを設定します
- 長時間のタスクにはハートビートを使用する - 進捗を報告します
- エラーを処理する - リトライ可能なエラーとリトライ不可能なエラーを区別します
よくある落とし穴
ワークフロー違反:
workflow.now()ではなくdatetime.now()を使用する- ワークフローコード内でスレッド処理や非同期処理を行う
- ワークフローから外部 API を直接呼び出す
- ワークフロー内で非決定的なロジックを使用する
アクティビティに関するミス:
- 冪等でない操作(再試行に対応できない)
- タイムアウトの設定漏れ(アクティビティが永久に実行され続ける)
- エラーの分類がない(検証エラーを再試行する)
- ペイロードの上限を無視する(引数ごとに 2MB)
運用上の考慮事項
監視:
- ワークフローの実行時間
- アクティビティの失敗率
- 再試行回数とバックオフ
- 保留中のワークフロー数
スケーラビリティ:
- ワーカーによる水平スケーリング
- タスクキューのパーティショニング
- 子ワークフローへの分解
- 適切な場合のアクティビティのバッチ処理
追加リソース
公式ドキュメント:
- Temporal の主要概念: docs.temporal.io/workflows
- ワークフローのパターン: docs.temporal.io/evaluate/use-cases-design-patterns
- ベストプラクティス: docs.temporal.io/develop/best-practices
- Saga パターン: temporal.io/blog/saga-pattern-made-easy
主要な原則:
- ワークフロー = オーケストレーション、アクティビティ = 外部呼び出し
- ワークフローでは決定性が必須です
- アクティビティでは冪等性が重要です
- 状態は自動的に保持されます
- 失敗と復旧を考慮して設計します