やったもん勝ち

主にプログラミングのこと。生産性向上の某とかも。

AWS Lambdaでdatetimeを使うときにコンテナが再利用される罠

lambdaのpythondatetimeを使おうとしてコードを書いて、いざ動かしてみると、どうもちょっとおかしい。
明らかにおかしいというよりは時折おかしくなることがある。
これが逆に厄介でした。
原因は、lambdaの実行コンテナのコンテキストは再利用されることがあるためでした。

こちらの公式ドキュメントに詳しく書いてあります。

docs.aws.amazon.com

たとえば、Lambda 関数がデータベース接続を確立する場合、連続した呼び出しでは接続を再確立する代わりに元の接続が使用されます。接続を作成する前に接続が存在するかどうかを確認するロジックをコードに追加することをお勧めします。

DB接続なんかの情報も再利用されるとのことで、いつかつまづきそうな気がするので書いておく。
datetimeも、先頭の方で定義しておくだけだと、ずっとそれが使い回されるようです。

じゃあ、どうすればいいか。
こちらの記事のコメントにありました。

qiita.com

lambda_handler関数の中で逐一定義してあげればいいのだそうです。

本当かどうか、検証コード書いて試してみます。

import json
from datetime import datetime

dt_global = datetime.now()

def lambda_handler(event, context):
    dt_inside = datetime.now()
    dt_inside_str = dt_inside.strftime('%Y-%m-%d %H:%M:%S')
    dt_global_str = dt_global.strftime('%Y-%m-%d %H:%M:%S')

    # こちらは毎実行ごとに取得される
    print(f"dt_inside: {dt_inside_str}")

    # こちらはコンテナが再利用される限り変更されない
    print(f"dt_global: {dt_global_str}")
    
    return ''

確かに、テスト実行を連打してみると、dt_globalの方は更新されていないのに、dt_insideは毎回更新されています。

これで1ヶ月くらいずっと正常に動いてたと思っていたlambdaがおじゃんになりました〜