📝

Lambda の再帰ループ検出されないパターンを試してみた

に公開

Lambda 再帰ループ検出を使用した無限ループの防止 - AWS Lambda

Amazon DynamoDB などの別の AWS のサービス がループの一部を形成してる場合、現時点では Lambda はそのループを検出して停止することはできません。

現時点では、Lambda は Amazon SQS、Amazon S3、および Amazon SNS に関連する再帰ループのみを検出するため、他の AWS のサービス が関与するループによって Lambda 関数が意図しない形で使用される可能性があります。

本ブログ執筆時点では上記のサポート状況であるため、サポートされていないサービスがループに含まれている場合には再帰ループは検出されません。
今回は以下の構成で再帰ループが検出されないことを確認してみました。

Starting a Step Functions workflow in response to events - AWS Step Functions

Lambda

以下のコードで S3 にテキストファイルをアップロードします。
なお、test.txt は index.js と同じディレクトリに作成済みです。

index.js
const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");
const fs = require("fs").promises;
const path = require("path");
const s3 = new S3Client({ region: REGION });

exports.handler = async function (event) {
  try {
    const filePath = path.join(__dirname, "test.txt");
    const fileContent = await fs.readFile(filePath);

    const uploadParams = {
      Bucket: my-bucket-name,
      Key: "test.txt",
      Body: fileContent,
      ContentType: "text/plain"
    };

    await s3.send(new PutObjectCommand(uploadParams));

    console.log("File uploaded successfully.");
    return {
      statusCode: 200,
      body: JSON.stringify({ message: "File uploaded successfully." })
    };
  } catch (error) {
    console.error("Error uploading file:", error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: "Failed to upload file." })
    };
  }
};

Step Functions

以下の定義で作成しました。
上記 Lambda を呼び出すだけです。

{
  "Comment": "A description of my state machine",
  "StartAt": "Lambda Invoke",
  "States": {
    "Lambda Invoke": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Output": "{% $states.result.Payload %}",
      "Arguments": {
        "FunctionName": "arn:aws:lambda:ap-northeast-1:012345678901:function:test:$LATEST",
        "Payload": "{% $states.input %}"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "IntervalSeconds": 1,
          "MaxAttempts": 3,
          "BackoffRate": 2,
          "JitterStrategy": "FULL"
        }
      ],
      "End": true
    }
  },
  "QueryLanguage": "JSONata"
}

EventBridge ルール

以下のイベントパターンを定義しました。

{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["my-bucket-name"]
    }
  }
}

ターゲットは上記 Step Functions ステートマシンです。

S3 バケット

Amazon EventBridge を有効にします - Amazon Simple Storage Service
EventBridge への通知の送信を許可します。

動作確認

Lambda 再帰ループ検出を使用した無限ループの防止 - AWS Lambda

同じリクエストチェーンで関数が 16 回ほど呼び出された場合、Lambda はそのリクエストチェーン内の次の関数呼び出しを自動的に停止し、ユーザーに通知します。

Lambda の再帰ループ検出が機能した場合には 16 回ほどで呼び出しが停止されます。
Lambda をテスト実行後、Step Functions ステートマシンの実行履歴は 1 ~ 2 秒間隔で増えていきましたが 101 回連続で記録されていたため、再帰ループ検出は機能しませんでした。

以上より、冒頭のドキュメントの記載通り「他の AWS のサービス が関与するループ」は検出されないことを確認できました。

まとめ

今回は Lambda の再帰ループ検出されないパターンを試してみました。
どなたかの参考になれば幸いです。

参考資料

Discussion