Step Functionsステートマシンで実行したLambda関数の戻り値のペイロードをパースする

2021.11.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

AWS Step Functionsステートマシンで実行したLambda関数の戻り値のペイロードをパースする方法を調べていたところ、ステートマシンからのLambda関数の実行のされ方は2種類あったので、それぞれについて確認してみました。

方法

AWS CDKで実装したステートマシンで確認してみます。

CDKコード

lib/aws-cdk-app-stack.ts

import * as cdk from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as tasks from '@aws-cdk/aws-stepfunctions-tasks';
import * as lambda from '@aws-cdk/aws-lambda';
import * as lambdaNodejs from '@aws-cdk/aws-lambda-nodejs';

export class AwsCdkAppStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    //Lambda関数
    const lambdaFunc = new lambdaNodejs.NodejsFunction(this, 'lambdaFunc', {
      entry: 'src/lambda/sampleHandler.ts',
      handler: 'handler',
      runtime: lambda.Runtime.NODEJS_14_X,
    });

    //Lambda関数実行タスク1
    const lambdaInvokeTask1 = new tasks.LambdaInvoke(
      this,
      'lambdaInvokeTask1',
      {
        lambdaFunction: lambdaFunc,
        resultSelector: {
          'payload1.$': '$.Payload',
        },
      }
    );

    //Lambda関数実行タスク2
    const lambdaInvokeTask2 = new tasks.CallAwsService(
      this,
      'lambdaInvokeTask2',
      {
        service: 'lambda',
        action: 'invoke',
        parameters: {
          FunctionName: lambdaFunc.functionName,
        },
        iamResources: [lambdaFunc.functionArn],
        iamAction: 'lambda:InvokeFunction',
        resultSelector: {
          'payload2.$': 'States.StringToJson($.Payload)',
        },
      }
    );

    //ステートマシン
    new sfn.StateMachine(this, 'stateMachine', {
      definition: lambdaInvokeTask1.next(lambdaInvokeTask2),
    });
  }
}

さてステートマシンのタスクでLambda関数を実行するメソッドは、LambdaInvoke()CallAwsService()の2つがあります。

Workflow Studioで言うと、LambdaInvoke()はIntegration TypeがOptimizedのパターンに対応しており、

CallAwsService()は[AWS SDK]のパターン対応しています。

そしてCallAwsService()の場合は戻り値のペイロードが必ず文字列となるため、ステートマシンでJson形式の戻り値をパースしたい場合はStates.StringToJson()を使用する必要があります。

Lambdaコード

戻り値のペイロードとして{ value: 123 }というJsonを返すLambdaです。

export const handler = async () => {
  return { value: 123 };
};

動作

ステートマシンを実行して動作を見てみます。

LambdaInvoke()を使用してLambdaを実行したタスクでは、Lambdaの戻り値のペイロードが{"value":123}とJson形式となっており、そのままステートマシンで使用できる形式となっています。

CallAwsService()を使用してLambdaを実行したタスクでは、Lambdaの戻り値のペイロードが"{\"value\":123}"と文字列形式となっており、States.StringToJson()を使用することでパースできています。

LambdaInvoke()とCallAwsService()のどちらを使えば良い?

LambdaInvoke()を使用するのが良いかと思います。理由は下記となります。

まとめ

  • ステートマシンで実行したLambda関数の戻り値のペイロードは、LambdaInvoke()を使用した場合は文字列化されないが、CallAwsService()を使用した場合は文字列化されるためStates.StringToJson()などでパースをする必要がある。
  • 基本的にはLambdaInvoke()を使用すれば良さそう。

以上