はじめに
出荷処理では、注文を保存してから、完了した注文のサマリーを読み取る必要があります。これらのタスクをワークフローで接続し、実行履歴を実際の業務結果と比較します。
先に Lambda から DynamoDB を読み書きする と、その前提となる IAM ロールとログのラボを完了してください。この独立した VM は、ワーカーとテーブルを提供します。ワークフローは自分で作成します。EventBridge のルーティングは別の学習経路です。
認定試験との関連
このラボでは、次の試験トピックに関連する実践的な演習を行います。
- Solutions Architect – Associate (SAA-C03) · タスク 2.1: Step Functions のタスクオーケストレーションと業務結果の検証。
- Developer – Associate (DVA-C02) · タスク 1.1: Step Functions のタスクオーケストレーションと業務結果の検証。
- DevOps Engineer – Professional (DOP-C02) · タスク 5.1, タスク 2.3: 基礎演習:Step Functions のタスクオーケストレーションと業務結果の検証。
- Solutions Architect – Professional (SAP-C02) · タスク 2.4: 基礎演習:Step Functions のタスクオーケストレーションと業務結果の検証。
ワークフローによるワーカー呼び出しを認可する
このステップでは、提供された業務ワーカーを確認し、Step Functions 用の独立した実行ロールを作成します。

ワークフローロールは関数を呼び出します。独立した Lambda ロールがテーブル操作を実行します。
Terminal の隣で AWS View を使い、CLI クエリをこのラボの実際のリソースと結果と比較します。提供された参照データを保持してください。
ワークフローはタスクと判断を接続します。ステートマシンはそれらの状態を定義し、実行は特定の入力でその定義を動かします。この新しい VM は、ワーカー関数と独立した注文・診断・参照テーブルを提供します。ステートマシンやワークフローロールはまだありません。ワーカーは注文を受け取り、数量と合計を書き込み、後でサマリーを読み取れます。その Lambda 実行ロールは、ワークフロー自体の操作とは別の、これらのテーブル操作をすでに認可しています。
プロジェクトディレクトリから始めます。シェルの代入は返された識別子を保存します。--query はレスポンスフィールドを選択し、--output text は再利用可能な文字列を生成します。
cd /home/labex/project
WORKER_NAME=labex-ev03-worker
WORKER_ARN=$(aws lambda get-function-configuration \
--function-name labex-ev03-worker \
--query FunctionArn \
--output text)
aws lambda get-function-configuration \
--function-name labex-ev03-worker \
--query '{Name:FunctionName,Role:Role,Runtime:Runtime,Timeout:Timeout}'
aws stepfunctions list-state-machines
ワーカーは Python3.12 と独自の Lambda ロールを使い、ステートマシン一覧は空です。Step Functions には自身の実行ロールが必要です。信頼ポリシーは Step Functions サービスによるそのロールの引き受けを許可し、権限ポリシーは、生成されたセッションがこのワーカーだけを呼び出すことを許可します。引用符付きのヒアドキュメントは JSON をそのまま書き込み、file:// はそれをリクエストに読み込みます。
cat > workflow-trust.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
JSON
ROLE_ARN=$(aws iam create-role \
--role-name labex-ev03-workflow-role \
--assume-role-policy-document file://workflow-trust.json \
--query Role.Arn \
--output text)
通常の権限ドキュメントを書き込みます。シェルは $WORKER_ARN を挿入し、この権限付与を提供されたワーカーに限定します。
cat > workflow-invoke.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "$WORKER_ARN"
}
]
}
EOF
aws iam put-role-policy \
--role-name labex-ev03-workflow-role \
--policy-name InvokeWorker \
--policy-document file://workflow-invoke.json
aws iam get-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker
ポリシーには 1 つの正確な関数 ARN があります。Step Functions は、ワーカーの DynamoDB 権限を受け取りません。ワーカーは、独立した Lambda ロールを使ってそれらの呼び出しを行います。認可の検証を実行してください。
判断と 2 つの実際のタスクを定義する
このステップでは、数量を検証し、注文を保存して、実際のサマリーを読み取る注文ワークフローを定義します。

StoreOrder は実際のペイロードを saved.result に保存します。ReadSummary はその注文 ID を選択し、完了したサマリーを読み取ります。
Amazon States Language(ASL) は、JSON のステートマシン定義です。StartAt は最初の状態を選択します。Choice は、条件が一致するとその分岐を進み、それ以外は Default を進みます。Task はサービスを呼び出します。Next は状態を接続し、End: true は成功として終了し、Fail はエラーで終了します。
最適化された Lambda タスク統合は、arn:aws:states:::lambda:invoke を使います。Parameters は関数引数を提供します。.$ で終わるキーは JSONPath を評価し、$ は現在の入力全体を選択します。Lambda 統合は、メタデータと Payload を返します。ResultSelector はそのペイロードだけを保持し、ResultPath は元の注文入力を保持しながら saved の下へ挿入します。次のタスクは、保存された注文 ID を選択します。その OutputPath は、実際のサマリーペイロードだけを返します。
定義をそのまま書き込み、その後 jq --arg でワーカーのプレースホルダーを置き換えます。
cat > workflow-template.json <<'JSON'
{
"StartAt": "CheckQuantity",
"States": {
"CheckQuantity": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.quantity",
"NumericGreaterThan": 0,
"Next": "StoreOrder"
}
],
"Default": "Rejected"
},
"StoreOrder": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "WORKER_NAME",
"Payload.$": "$"
},
"ResultSelector": {
"result.$": "$.Payload"
},
"ResultPath": "$.saved",
"Next": "ReadSummary"
},
"ReadSummary": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "WORKER_NAME",
"Payload": {
"stage": "summary",
"id.$": "$.saved.result.id"
}
},
"OutputPath": "$.Payload",
"End": true
},
"Rejected": {
"Type": "Fail",
"Error": "OrderRejected",
"Cause": "Quantity must be positive"
}
}
}
JSON
jq --arg worker "$WORKER_NAME" '.States.StoreOrder.Parameters.FunctionName=$worker | .States.ReadSummary.Parameters.FunctionName=$worker' workflow-template.json > workflow.json
MACHINE_ARN=$(aws stepfunctions create-state-machine \
--name labex-ev03-orders \
--type STANDARD \
--role-arn "$ROLE_ARN" \
--definition file://workflow.json \
--query stateMachineArn \
--output text)
aws stepfunctions describe-state-machine \
--state-machine-arn "$MACHINE_ARN" \
--query '{Name:name,Role:roleArn,Definition:definition}'
レスポンスはステートマシンとワークフローロールを示し、定義は両方のタスクで提供されたワーカーを指定します。注文はまだ処理されていません。Terminal の隣の AWS View をクリックし、実際のステートマシン定義と空の実行・注文一覧を確認します。定義の検証を実行してください。
業務結果と拒否される実行を確認する
このステップでは、有効な注文、無効な数量、呼び出し権限のない実行を試します。
start-execution は非同期作業を開始し、実行 ARN を返します。以下の回数を限定したシェルループは、実行中でなくなるまで 2 秒ごとに状態を読み取ります。$(...) はコマンド出力を取得し、seq はループ回数を提供し、break は条件が一致したときにループを終了します。ループ後も RUNNING の場合は、先へ進む前にサービスを確認してください。
EXECUTION_ARN=$(aws stepfunctions start-execution \
--state-machine-arn "$MACHINE_ARN" \
--name valid-order \
--input '{"id":"workflow-order","quantity":3}' \
--query executionArn \
--output text)
for attempt in $(seq 1 60); do
STATUS=$(aws stepfunctions describe-execution \
--execution-arn "$EXECUTION_ARN" \
--query status \
--output text)
if test "$STATUS" != RUNNING; then break; fi
sleep 2
done
aws stepfunctions describe-execution \
--execution-arn "$EXECUTION_ARN" \
--query '{Status:status,Output:output}'
aws stepfunctions get-execution-history \
--execution-arn "$EXECUTION_ARN" \
--query 'events[].type'
aws dynamodb get-item \
--table-name labex-ev03-orders \
--key '{"id":{"S":"workflow-order"}}' \
--query Item

公式コンソールは、実行名と状態を時間情報とともに表示します。その名前とワークフローは、このラボの Standard ステートマシンとは異なります。自分の CLI 状態を履歴と保存データと比較し、このラボの結果には AWS View を使ってください。
状態は SUCCEEDED で、出力には注文 ID、total_cents:850、completed:true が含まれます。実際の DynamoDB アイテムは数量 3、合計 850 です。履歴には、注文保存とサマリー読み取りの 2 つの TaskSucceeded イベントがあります。実行状態だけでは業務結果を証明できません。両方を比較してください。
数量 0 で Choice 分岐をテストします。
INVALID_ARN=$(aws stepfunctions start-execution \
--state-machine-arn "$MACHINE_ARN" \
--name invalid-order \
--input '{"id":"invalid-order","quantity":0}' \
--query executionArn \
--output text)
for attempt in $(seq 1 30); do
STATUS=$(aws stepfunctions describe-execution \
--execution-arn "$INVALID_ARN" \
--query status \
--output text)
if test "$STATUS" != RUNNING; then break; fi
sleep 2
done
aws stepfunctions describe-execution \
--execution-arn "$INVALID_ARN" \
--query '{Status:status,Error:error}'
aws dynamodb get-item \
--table-name labex-ev03-orders \
--key '{"id":{"S":"invalid-order"}}' \
--query Item
状態は OrderRejected を伴う FAILED で、invalid-order アイテムはありません。Choice がワーカー呼び出し前に拒否しました。
次に、ワークフローの Invoke ポリシーだけを削除します。ワーカーのロールとデータ権限は独立したままです。操作担当者には引き続き実行開始が許可されていますが、ワークフローロールはタスクを呼び出せません。
aws iam delete-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker
DENIED_ARN=$(aws stepfunctions start-execution \
--state-machine-arn "$MACHINE_ARN" \
--name denied-order \
--input '{"id":"denied-order","quantity":2}' \
--query executionArn \
--output text)
for attempt in $(seq 1 30); do
STATUS=$(aws stepfunctions describe-execution \
--execution-arn "$DENIED_ARN" \
--query status \
--output text)
if test "$STATUS" != RUNNING; then break; fi
sleep 2
done
aws stepfunctions describe-execution \
--execution-arn "$DENIED_ARN" \
--query '{Status:status,Error:error}'
aws dynamodb get-item \
--table-name labex-ev03-orders \
--key '{"id":{"S":"denied-order"}}' \
--query Item
aws iam put-role-policy \
--role-name labex-ev03-workflow-role \
--policy-name InvokeWorker \
--policy-document file://workflow-invoke.json
拒否された実行は、呼び出し時にアクセス拒否エラーで失敗します。注文は作成せず、ワーカータスクも実行しません。意図するポリシーは復元されます。AWS View には、実際の成功したサマリーと両方の失敗が、1 件の保存された注文の隣に表示されます。
以下の例は、実際の成功したサマリー、拒否された実行、1 件の業務注文を示します。

実行の検証を行ってください。
ワークフローリソースと合成結果を削除する
このステップでは、提供された準備リソースを保持しながら、自分の完了したステートマシン、ワークフローロール、注文、ログを削除します。
3 つの実行はすべて終了しています。ステートマシンの削除は、アクティブなステートマシン一覧からそれを取り除きます。ロールを削除する前に所有するロールポリシーを削除し、その後、合成注文と実行によって作成されたワーカーロググループを削除します。
aws stepfunctions delete-state-machine --state-machine-arn "$MACHINE_ARN"
aws iam delete-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker
aws iam delete-role --role-name labex-ev03-workflow-role
aws dynamodb delete-item \
--table-name labex-ev03-orders \
--key '{"id":{"S":"workflow-order"}}'
aws dynamodb delete-item \
--table-name labex-ev03-attempts \
--key '{"id":{"S":"workflow-order"}}'
aws logs delete-log-group --log-group-name /aws/lambda/labex-ev03-worker
成功する一覧取得で、残るものを証明します。
aws stepfunctions list-state-machines
aws iam list-roles --query 'Roles[].RoleName'
aws dynamodb scan --table-name labex-ev03-orders --query Items
aws logs describe-log-groups --query logGroups
aws dynamodb scan --table-name labex-ev03-reference --query Items
アクティブなステートマシン、注文、ロググループはありません。提供されたワーカーロールだけが残り、参照アイテムは変わりません。提供されたワーカーとテーブルは保持してください。準備時の所有範囲は、自分が作成したワークフローやリソースと異なります。ネットワークエラーや認証エラーは削除の証拠になりません。
このラボで作成した通常のファイルを削除します。
rm -f workflow-trust.json workflow-invoke.json workflow-template.json workflow.json
AWS View には、空のステートマシン・実行・注文と、保持された参照リソースが表示されます。VM を終了する前に、後片付けの検証を実行してください。
まとめ
範囲を限定したワークフロー実行ロールを作成し、Choice と 2 つの実際の Lambda タスクを接続して、実際の結果を次のタスクへ渡し、実行履歴を業務データと比較しました。無効な入力と呼び出し権限の不足では、注文は生成されませんでした。提供された準備リソースを保持しながら、所有するワークフローリソースと合成結果を削除しました。
次のユニットでは、一時的な失敗の再試行と、永続的なエラーの明示的な処理を追加します。



