😎

SQSイベントにて発火されたLambda関数で例外処理をするときは「return」はしないで!!

2025/03/09に公開

お久し振りです!mikenekoです!
2025年は記事執筆に力を入れていこうと思っていましたが、
まだまだ執筆できていない感じですね。

記事を執筆する時間はないものの、zennのスクラップにメモ書きとURLを残すようにしているのですが
この運用が果たして私に合うのか。。(継続して1年ほど続けてみようかなと思っています!)

今回の記事は、本業でSQSイベント + Lambda関数を触っているときに起こった現象について記事を書こうと思いました!
割と見落としがちなミスだと思っていますのでぜひ参考になればです。

Lambda関数 ハンドラーについて

Lambda関数のハンドラーは、AWS Lambdaがイベントを受け取った際に実行されるエントリーポイントです。ハンドラーは、イベントデータとコンテキストオブジェクトを引数として受け取り、非同期処理を行うことができます。Node.jsを使用する場合、ハンドラーは通常、非同期関数として定義され、Promiseを返すことで非同期処理を管理します。

ハンドラーの役割は、受け取ったイベントデータを解析し、必要なビジネスロジックを実行することです。例えば、SQSイベントを処理する場合、ハンドラーはメッセージをデコードし、必要なアクションを実行します。エラーハンドリングも重要で、例外が発生した場合は適切に処理し、必要に応じて例外をスローすることで、Lambdaのリトライメカニズムを活用することができます。

詳細については以下の公式Docが参考になるかと思います!
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/typescript-handler.html

問題のあったソースコード

ほんの一部ですが、コードを記載します。
今回、本業でNode.jsを使用していたのでそちらの方でコードを記載していきます。
(公式ドキュメントにはPython, Javaなどありますのでそちらをご参照ください🙇)

export const handler = async (event, context) => {
  for (const record of event.Records) {
    try {
      // code ...
    } catch (error) {
      return { statusCode: 500 }
    }
  }
  return { statusCode: 200 };
};

上記のコードにて、例外が発生したときはLambda関数は成功したと判断します。
そのため、SQSとLambdaのような構成をとっている場合、特定の回数失敗した時にDLQへ自動的に送信する設定を入れていても、Lambda関数自体が成功と判断されるため、リトライ処理が行われないことがあります。

では、どうするか?

以下の公式Docの注記にも記載がある通り、関数が例外をスローする場合、バッチ全体が完全な失敗とみなされます。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/services-sqs-errorhandling.html#:~:text=使用します。-,注記,-部分的な

export const handler = async (event, context) => {
  for (const record of event.Records) {
    try {
      // code ...
    } catch (error) {
      // 受けとった例外をスローするようにする
      throw new Error("There is an error in the SQS Message.");
    }
  }
  return { statusCode: 200 };
};

SQSイベントからメッセージを受け取り、処理をしていきます。 その過程で例外をキャッチした場合、スローするのが妥当なのかなと思っています!
また、例外をキャッチした時にDLQへ送信するというような処理も記載できますが、そのあたりはマネージドサービスに任せてしまった方が管理が楽にもなると思っています。

Lambda関数の例外処理のベストプラクティス

Lambda関数を使用する際の例外処理について、いくつかのベストプラクティスを紹介します。

  1. 適切なエラーハンドリング: 例外が発生した場合、適切にエラーハンドリングを行い、リトライさせたい場合などは例外をスローさせるようにしましょう。
  2. ログの記録: エラーが発生した際には、詳細なログを記録することで、後から問題を特定しやすくなります。console.error()などで出力するようにしましょう。
  3. リトライポリシーの設定: SQSやLambdaのリトライポリシーを適切に設定することで、エラー発生時の自動再試行を行うことができます。デフォルトで3回行われるので適宜設定を変更しましょう。
  4. DLQの活用: デッドレターキュー(DLQ)を設定することで、処理に失敗したメッセージを別のキューに送信し、後から手動で再処理することができます。SQSを作成したときに一緒に作成するようにしておきましょう。

これらのベストプラクティスを守ることで、Lambda関数の信頼性と可用性を向上させることができます。

まとめ

今回は、SQSイベントとLambda関数を使用した際の例外処理について解説しました。例外処理はシステムの信頼性を保つために非常に重要な要素です。適切なエラーハンドリングとリトライポリシーの設定を行い、システムの安定性を確保しましょう。

今後も引き続き、AWSのサービスを活用した開発に関する記事を執筆していきたいと思いますので、よろしくお願いします!

Discussion