Help us understand the problem. What is going on with this article?

AWS LambdaのDestinationsを試してみる

AWSから割とすごい機能が発表されました。

Introducing AWS Lambda Destinations
https://aws.amazon.com/jp/blogs/compute/introducing-aws-lambda-destinations/

スクリーンショット 2019-11-27 6.51.44.png

Lambdaの実行結果に従って次のアクション(AWSサービス)を指定できる、というものです。
成功/失敗の条件で流れを制御したい場合には、Step Functionsを使う必要もなく、Lambdaだけで完結することができるようになりました。

早速試してみます。

呼び出し元のLambdaを適当に定義

こんな感じのPythonを書きます。(Python 3.7を利用)

import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def destination_sample_handler(event, context):
    logger.info("destination sample lambda started.")
    if event['Success'] == True:
        return {
            'statusCode': 200,
            'body': event
        }
    else:
        raise Exception('Success is False', event)

呼び出す際、event内にSuccess変数を定義し、その中身がTrueかFalseで判断を変えています。

Destinationを設定する

AWSブログではSNSとLambdaで成功/失敗の呼び出し先を変えてますが、手を抜いて両方Lambdaにしちゃいます。

Lambda関数にアクセスした際に、「Designer」パート「Cofiguration」タグ内に、「Add destination」という項目が見つかるはずです。

スクリーンショット 2019-11-29 7.10.51.png

こちらは成功パターン
スクリーンショット 2019-11-27 7.16.10.png

成功パターンの中身はこんな感じ。ただLogに出力しているだけです。

import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info("Success dest lambda started.")
    logger.info(event)
    return {
        'statusCode': 200,
        'message': 'Success in dest lambda',
        'body': event
    }

こちらは失敗のDestination設定
スクリーンショット 2019-11-27 7.18.20.png

中身は成功パターンと同じです

import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info("Failure dest lambda started.")
    logger.info(event)
    return {
        'statusCode': 200,
        'message': "Failure in dest lambda",
        'body': event
    }

実行してみる

実行はCLIから実施します。

$ aws lambda invoke --function-name destination-sample --invocation-type Event --payload '{ "Success": false }' response.json
{
    "StatusCode": 202
}

実行が成功すると202がStatusCodeとして返ってくるようです。

成功

成功させて見ると成功側のCloudWatch Logsにこんな感じの出力がありました。
CloudWatch Logs

[INFO]  2019-11-26T22:26:49.792Z    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx    {'version': '1.0', 'timestamp': '2019-11-26T22:26:49.425Z', 'requestContext': {'requestId': '26fab6f9-a2b7-45f2-bce2-47c612cdb8b7', 'functionArn': 'arn:aws:lambda:us-east-1:000000000000:function:destination-sample:$LATEST', 'condition': 'Success', 'approximateInvokeCount': 1}, 'requestPayload': {'Success': True}, 'responseContext': {'statusCode': 200, 'executedVersion': '$LATEST'}, 'responsePayload': {'statusCode': 200, 'body': {'Success': True}}}

呼び出し先のeventの中身をログ出力しましたが、以下のようになっているようです。

  • conditionに成功/失敗が入る
  • requestPayloadに大元の呼び出し元eventが入る
  • responsePayloadに呼び出し元からreturnされた値が入る

少しコードを編集してeventにMessage要素を入れたところ、responsePayloadの中身が追加されました。

    if event['Success'] == True:
        event['Message'] = "Successful finished."
        return {
            'statusCode': 200,
            'body': event
        }
[INFO]  2019-11-26T23:41:21.229Z    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx    {'version': '1.0', 'timestamp': '2019-11-26T23:41:20.730Z', 'requestContext': {'requestId': 'ba73f7a2-77f4-4166-a95d-d43020e5cc32', 'functionArn': 'arn:aws:lambda:us-east-1:000000000000:function:destination-sample:$LATEST', 'condition': 'Success', 'approximateInvokeCount': 1}, 'requestPayload': {'Success': True}, 'responseContext': {'statusCode': 200, 'executedVersion': '$LATEST'}, 'responsePayload': {'statusCode': 200, 'body': {'Success': True, 'Message': 'Successful finished.'}}}

ちなみに成功時のDestinationを一つ増やしたところ、On success側の設定が上書きされました。一つの条件に対して呼び出せるサービスは一つのようです。

スクリーンショット 2019-11-27 8.55.42.png

Add destinationを実施してもOn successの呼び出し先が上書きされるだけ。

スクリーンショット 2019-11-27 8.40.59_deco.png

失敗

失敗側も似たようなログがCloudWatch Logsに出ました。

[INFO]  2019-11-26T22:30:46.594Z    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx    {'version': '1.0', 'timestamp': '2019-11-26T22:30:46.203Z', 'requestContext': {'requestId': '6fc2d258-fafb-40a2-8d18-886df8510fa1', 'functionArn': 'arn:aws:lambda:us-east-1:000000000000:function:destination-sample:$LATEST', 'condition': 'RetriesExhausted', 'approximateInvokeCount': 3}, 'requestPayload': {'Success': False}, 'responseContext': {'statusCode': 200, 'executedVersion': '$LATEST', 'functionError': 'Unhandled'}, 'responsePayload': {'errorMessage': "('Success is False', {'Success': False})", 'errorType': 'Exception', 'stackTrace': ['  File "/var/task/lambda_function.py", line 17, in destination_sample_handler\n    raise Exception(\'Success is False\', event)\n']}}

Exceptionの中身もきちんと伝搬してますね。

ちなみにX-Rayでの表示は?

X-RayではきちんとLambdaから処理が分岐しました。想像した通りとはいえ、これはすごい。ほぼこれでトレースもできますね。

スクリーンショット 2019-11-27 8.51.34.png

まとめ

簡単に成功/失敗での処理の分岐が実現できてしまいました。ちょっとしたスクリプトの制御であればこれで十分ですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away