← AWSサービスの内部原理 コース
93. タスクトークンは呼び戻しの合言葉である — ポーリングせずに人間の承認を1年待てる
ワークフローを止めて外の世界(人間の承認・サードパーティ・レガシー)に仕事を投げ、「合言葉」を持った者だけがそれを起こせる——waitForTaskTokenパターンの流れを、1枚ずつ図で追っていきます。
① 継続を「合言葉」として外に渡す
接尾辞を付けるarn:aws:states:::sqs:sendMessage.waitForTaskToken
.waitForTaskToken がスイッチASLからはContextオブジェクト経由で取り出す
専用トークン生成推測不能なランダム文字列
例: h7XRiCdLtd/83p1E0dMccoxlzFhglsdkzpK9mBVKZsp7d9yrT1W$$.Task.Token"TaskToken.$": "$$.Task.Token"
$$=Contextオブジェクト / .$=「値はパスだ」の印- Resource文字列に付ける3つの統合パターンは Request Response(接尾辞なし)/ .sync(ジョブ完了まで待つ)/ .waitForTaskToken(トークンが返るまで待つ)の3種。この回は3つ目。
- 公式の言い回し: 「When you specify a resource using .waitForTaskToken, the task token can be accessed in the "Parameters" field of your state definition with a special path designation ($$.Task.Token).」
- $$. はContextオブジェクトへのパス。$(一重)が入力データへのパスなのに対し、$$(二重)は実行自身のメタデータ。中身は Execution(Id・Input・Name・RoleArn・StartTime)・State(EnteredTime・Name・RetryCount)・StateMachine・Task.Token。実行ID・状態名・リトライ回数はここに入っている。
.waitForTaskTokenを付けた瞬間、Step Functionsはそのタスク専用の推測不能なトークンを1つ発行する。SQSに積むのは処理データではなく、この「あとで続きを実行する権利(=継続)」そのものだ。
② トークンを外の世界へ同梱し、ワークフローは眠る
ワークフロー実行中
送信した後、タスク状態はここで停止
SQSメッセージ"TaskToken.$": "$$.Task.Token"
トークンごと外の世界へ待てる長さ = Standardワークフローの実行上限
トークン待ちで眠る処理は完全に停止・ループは一切回らない
CPUを回して待つのではなく、イベントログ上の「待ち」状態最大1年
- 公式: 「you can pause Step Functions until the workflow execution reaches the one year service quota ... and wait for an external process or workflow to complete.」
- 対比の核心: ポーリング(こちらから完了を聞きに行く)ではなく、停止して待つ。聞きに行くループは1つも回っていない。
- .waitForTaskTokenはStandardワークフローでのみサポート(Express Workflowsは Request Response のみ)。1年待つ設計はStandard前提。
メッセージング編で「SQSに積むのはデータ」と見たが、ここで積んでいるのは再開の権利だ。ワークフローは計算を回さず、ログ上の「待ち」状態として最大1年眠れる——ポーリングでは決して到達できない待ち方。
③ 合言葉を持つ者だけが起こせる
眠っている実行トークン待ち
起こせるのはトークンを持つ者だけtaskTokenを添えて1回だけ呼ぶ
人間の承認UI
サードパーティ
レガシーシステム
呼ばれて初めてワークフローが動く
SendTaskSuccesstaskToken + 結果JSON
SendTaskFailuretaskToken + エラー
次の状態へ進む
タスク失敗として遷移
- 公式: 「When it's complete, the external service calls SendTaskSuccess or SendTaskFailure with the taskToken included. Only then does the workflow continue to the next state.」
- SendTaskSuccess には結果のJSON(outputパラメータ・必須)を添え、それがタスクの出力になる。
- 重要な制約(公式の強い言い回し): 「You must pass task tokens from principals within the same AWS account. The tokens won't work if you send them from principals in a different AWS account.」——合言葉は同一AWSアカウントのプリンシパルから返さないと効かない。
- ポーリング型との対比: ポーリングは呼び出し側が「終わった?」と何度も聞きに行きムダな問い合わせが続く。waitForTaskToken型は外部プロセスが「終わったぞ、合言葉はこれだ」と1回だけ呼ぶ。
起こす権利はトークンの所持だけで決まる。呼び出し側が「終わった?」と聞いて回る(ポーリング)のではなく、合言葉を持った外部プロセスが1回呼べば目を覚ます——メッセージング編の「ポーリング vs プッシュ」の完成形だ。
④ 誰も呼び戻してくれない事故への備え — HeartbeatSeconds
トークン待ちのタスク"HeartbeatSeconds": 600
「生きている証拠を600秒ごとに出せ」と宣言間隔内に届いたか?
SendTaskHeartbeattaskTokenを添えて「まだ生きている」
届いた待機を継続
600秒途絶えたタスク失敗: States.Timeout
- 公式例: 「"HeartbeatSeconds": 600」= ハートビート間隔10分。「If the waiting task doesn't receive a valid task token within that 10-minute period, the task fails with a States.Timeout error name.」
- 待ち受けられる呼び戻しAPIは3つ: SendTaskSuccess / SendTaskFailure / SendTaskHeartbeat。ハートビートはハートビート時計をリセットするだけで、ワークフローは眠り続ける(APIリファレンス: 「This action resets the Heartbeat clock.」)。
- 補足: タスクに TimeoutSeconds を設定している場合、それはハートビートを何回受信しても超えられない最大許容時間。ハートビート間隔の設定は HeartbeatSeconds の役割(APIリファレンスの注記より)。
- HeartbeatSecondsを付けなければタスクは1年の上限まで宙吊りになりうる。ハートビートは「無限の宙吊り」を防ぐ安全弁。
これはメッセージング編の可視性タイムアウトと同じ原理の再登場——「生存を証明し続けないと死んだとみなす」。ハートビートが途絶えればStates.Timeoutで失敗させ、誰も呼び戻さない事故で永遠に眠り続けるのを防ぐ。
⑤ タイムアウトで合言葉は無効になる — トークンの再生成
トークンT1で待機中
新しいランダムなトークンが生成される
Task状態がタイムアウト
古いT1は無効SendTaskSuccessしても起こせない
新しいT2が有効
- 公式: 「If a Task state using the callback task token times out, a new random token is generated.」
- 期限切れトークンで呼んだ場合の挙動もAPIリファレンスに明記: SendTaskSuccess は TaskTimedOut エラーを返す——「The task token has either expired or the task associated with the token has already been closed.」
- 帰結: 遅れて返ってきた古いトークンは効かない。合言葉が使い捨てだからこそ、「タイムアウトしたのに後から結果が届いて二重進行する」事故が起きない。
トークンは推測不能かつ使い捨ての合言葉だ。タイムアウトすれば古い合言葉は失効し、新しいものに置き換わる——これは認証暗号編で見た一時的認証情報や署名付きURLと同型のcapability設計。「権利そのものを推測不能な文字列で表す」という考え方だ。