Skip to main content

第12章:Orchestration入門(司令塔の役割)🎻🧠

この章でできるようになること🎯✨

  • 「オーケストレーション(司令塔方式)」が何かを説明できる😊
  • 司令塔(Orchestrator)が判断すること/しないことを整理できる🧹
  • “最小Saga”の司令塔ToDoリストを自分で書ける📝💖

1) Orchestrationってなに?🎻✨(ひとことで)

オーケストレーションは、中央の司令塔(オーケストレーター)が、各サービスに「次はこれやってね」って指示して、進捗を記録して、失敗したら補償も指示する方式だよ📣🧾 MicrosoftのAzure Architecture Centerでも、オーケストレーターが状態を保存し、各タスクの状態を解釈し、補償トランザクションで回復すると説明されてるよ📚✅ (Microsoft Learn)


2) たとえ話でイメージする🎬🛒💳📦

「注文の旅」を想像してみよ〜🚶‍♀️✨ 例:

  1. 注文を作る🛒
  2. 決済する💳
  3. 在庫を確保する📦
  4. 発送手配する🚚

✅ 司令塔方式だとこうなる

  • 司令塔が「次は決済ね!」って指示する🎻📣
  • 各サービスは、言われたことを実行して「できたよ/失敗したよ」を返す📨
  • 司令塔は「今どこまで成功したか」を記録する🧾
  • 途中で失敗したら、司令塔が「じゃあ戻そう!」って補償を逆順で指示する🧯🔁

Orchestrator Role


3) 司令塔が判断すること(超重要)🧠✅

司令塔の仕事は「実行」じゃなくて「指揮」だよ🎻✨ 代表的にはこんな感じ👇

3.1 次に進むか?止めるか?を決める🚦

  • Step Aが成功 → Step Bへ✅
  • Step Bが失敗 → 補償へ🧯
  • タイムアウトした → 失敗扱い?リトライ?⏰

3.2 “進捗”を記録する📍🧾

  • どこまで終わった?
  • どのStepが成功した?
  • いま状態は何?(実行中/補償中/完了…)

AzureのSagaパターン説明でも、オーケストレーターが状態を保存して判断するとされてるよ🗂️ (Microsoft Learn)

3.3 失敗時に「補償」を発動する🧯🔁

  • 成功したStepだけを逆順で戻す(できる範囲で)
  • 補償が失敗したら? → 追加のエラー扱い(人手対応や再試行)へ🚨

4) 司令塔が “やらないこと” も決めよう🙅‍♀️🧱

ここ、設計が急に上手くなるポイントだよ✨

❌ 司令塔に入れない方がいいもの

  • 決済の細かいロジック全部💳(それは決済サービスの責務)
  • 在庫計算の詳細📦(在庫サービスの責務)
  • 発送会社ごとの分岐地獄🚚(発送サービスの責務)

✅ 司令塔が持つのは「薄い判断」

  • 成功/失敗の判定
  • 次のStepの選択
  • 状態の記録
  • 補償の開始と順番

5) Orchestrationの“強み”と“弱み”🌟🧯

🌟 強み(学びやすい&運用しやすい)

  • 流れが一箇所で見える👀✨
  • ログ・監視がまとめやすい🔎
  • 失敗時の補償も、司令塔中心で整理できる🧠

🧯 弱み(やりすぎ注意)

  • 司令塔が肥大化しがち🍔💦
  • 司令塔が止まると全体が止まりやすい🛑 → だから「やらないこと」を決めるのが大事だったね🙆‍♀️✨

6) “最小構成”の全体図(コマンドと結果)🗺️📨

司令塔方式は、ざっくりこういう会話になるよ👇

  • 司令塔 → 決済サービス:「決済して」📣
  • 決済サービス → 司令塔:「成功したよ/失敗したよ」📨
  • 司令塔 → 在庫サービス:「在庫確保して」📣
  • 失敗したら:司令塔 → 「補償して」🧯

この “指示→結果→次を決める” の繰り返しが、オーケストレーションの心臓部だよ💓🎻


7) TypeScriptで見る「司令塔の骨格」🦴🧑‍💻

ここでは最小の形を見て、頭の中に型を作るよ😊✨ (本格実装は次章以降で育てていくイメージ🌱)

type SagaStatus =
| "PENDING"
| "RUNNING"
| "COMPLETED"
| "FAILED"
| "COMPENSATING"
| "COMPENSATED";

type StepResult = { ok: true } | { ok: false; reason: string };

type Step = {
name: string;
run: () => Promise<StepResult>;
compensate?: () => Promise<void>;
};

type SagaLog = {
sagaId: string;
status: SagaStatus;
executed: string[]; // 実行済みStep名(順方向)
startedAt: number;
updatedAt: number;
lastError?: string;
};

async function runSaga(sagaId: string, steps: Step[]): Promise<SagaLog> {
const log: SagaLog = {
sagaId,
status: "RUNNING",
executed: [],
startedAt: Date.now(),
updatedAt: Date.now(),
};

try {
for (const step of steps) {
const result = await step.run();

if (!result.ok) {
throw new Error(`[${step.name}] failed: ${result.reason}`);
}

log.executed.push(step.name);
log.updatedAt = Date.now();
}

log.status = "COMPLETED";
log.updatedAt = Date.now();
return log;
} catch (e) {
log.status = "FAILED";
log.lastError = e instanceof Error ? e.message : String(e);
log.updatedAt = Date.now();

// 補償フェーズ(逆順)
log.status = "COMPENSATING";
log.updatedAt = Date.now();

const executedSteps = steps.filter(s => log.executed.includes(s.name)).reverse();
for (const step of executedSteps) {
if (step.compensate) {
await step.compensate();
}
}

log.status = "COMPENSATED";
log.updatedAt = Date.now();
return log;
}
}

ここで押さえるポイント✅✨

  • 司令塔は「順方向Step」を順番に実行しつつ、実行済みを記録してる📒

  • 失敗したら、実行済みだけを逆順に補償してる🧯🔁

  • この章では「骨格」だけ!

    • 本当はここに、タイムアウト⏰/リトライ🔁/冪等性🔑/永続化🗂️/観測性🔎 が乗ってくるよ(後の章でちゃんとやる💪)

8) 「自作オーケストレーター」以外の選択肢もあるよ🧰✨(最新の代表例)

実務だと、司令塔を“自作”だけでなく、ワークフロー基盤に任せることも多いよ😊

  • Temporal:Saga(補償)を含む長期ワークフローを扱う代表例。Sagaをワークフロー内のパターンとして紹介してるよ📚 (docs.temporal.io)

    • Temporalは「ワークフローをリプレイできる(durable execution)」ために、ワークフロー側のコードに“決定性”が必要…みたいな考え方も出てくるよ🔁🧠 (learn.temporal.io)
  • AWS Step Functions:サーバーレスでSaga(補償)を組み立てる設計例が公式にあるよ☁️📮 (AWS ドキュメント)

  • Azure(設計パターンとしてのSaga):オーケストレーション/コレオグラフィの両方を整理してるよ🧾 (Microsoft Learn)

ここでは「そういう道具もあるんだ〜」くらいでOK🙆‍♀️ まずは “司令塔の考え方” を体に入れるのが勝ち✨🎻


9) 章末演習:司令塔ToDoを書き出そう📝🎻💖

次の「注文フローSaga」を想定して、司令塔のToDoを書いてみてね😊 (答えは1つじゃないよ✨)

お題🛒

  • Step1:注文作成
  • Step2:決済
  • Step3:在庫確保
  • Step4:発送手配

9.1 ToDoテンプレ(これを埋めるだけでOK)✅

  1. 司令塔が持つSaga IDは?🆔
  2. 状態(Status)は何種類にする?📍
  3. 進捗として最低限何を保存する?🧾
  4. Stepごとの「成功の判定」は何?✅
  5. Stepごとの「失敗時の補償」は何?🧯
  6. タイムアウトはどこにかける?⏰(決済?在庫?)
  7. リトライして良い失敗/ダメな失敗はどれ?🔁⚠️
  8. ログに残すべき“調査用の情報”は何?🔎

9.2 追加ミニ問題(サクッと)💡

  • 「司令塔がやらないこと」を3つ書こう🙅‍♀️🧱
  • 司令塔方式が分かりやすい理由を、1文で書こう✍️✨

コラム:TypeScriptの“いま”をちょいだけ👀⚡

大規模コードベースで設計を回すとき、コンパイル速度もけっこう大事だよね😊 TypeScriptは 5.9がリリースされていて、さらに TypeScript 7(Project Corsa)としてGo移植による大幅高速化の話が進んでるよ🚀 (Microsoft for Developers) (型で状態機械を作るような設計とも相性が良くなる流れ〜✨🧠)