Cloud Functions における SQLAlchemy 利用の注意点

Cloud Functions における SQLAlchemy 利用の注意点

SQLAlchemy

SQLAlchemy は、Python でよく利用される ORM (Object Relational Mapper) です。
データベースとの接続において、テーブルとクラスを対応させることができ、 SQL を書かずともデータの取得・追加・変更・削除などを容易に行うことができます。
https://www.sqlalchemy.org/
SQLAlchemy の利用方法については、公式のチュートリアルや多くの開発ブログで紹介されていますので、ここでは取り扱いません。しかし、 Cloud Functions で利用していたときに、正しくデータを取得できないケースがあったため、そのようなことが起きないように注意点を紹介したいと思います。

よくあるデータ登録方法

Cloud Functions において SQLAlchemy を利用してデータを登録するとき、次のように書くでしょう。
def get_data(request):
    try:
        session = Session()
        user = User()
        user.name = 'hogehoge'
        session.add(user)
        session.commit()

    except Exception as e:
        print('Error: {}'.format(str(e)))

よくあるデータ取得方法

一方、データを取得するときは、次のように書くでしょう。
def get_data(request):
    try:
        session = Session()
        user = session.query(User).filter(User.name == 'hogehoge').first()
        print(user)

    except Exception as e:
        print('Error: {}'.format(str(e)))
一般的なサーバであれば、データ登録後に直ぐにデータを取得しても問題なく正常なデータを取得することができるでしょう。また Cloud Functions のためにローカルで functions-framework コマンドを利用したサーバにおいても正常にデータを取得できることを確認しました。

しかし、本番用に Cloud Functions へデプロイしたときは、データを更新したのにその後直ぐにデータを取得しようとしても、古いデータが取り出されることがあります。

何が問題なのかお気づきでしょうか。実は Session を使い回しているのが原因でした。一般的なサーバでは同じ Session を利用することになるので最新の情報が出力されますが、 Cloud Functions の場合は、関数毎に Session が異なります。
Session は直近の情報を保持していますので、データ変更が行われても他の Session は知る由がありません。 Cloud Functions ではリクエスト毎に Session を閉じた方が良さそうです。

次のように session.close() を追加すればいいでしょう。

関数毎にセッションを閉じるデータ登録方法

def get_data(request):
    try:
        session = Session()
        user = User()
        user.name = 'hogehoge'
        session.add(user)
        session.commit()
        session.close()

    except Exception as e:
        print('Error: {}'.format(str(e)))

関数毎にセッションを閉じるデータ取得方法

def get_data(request):
    try:
        session = Session()
        user = session.query(User).filter(User.name == 'hogehoge').first()
        print(user)
        session.close()

    except Exception as e:
        print('Error: {}'.format(str(e)))

まとめ

私は今回の問題で一日を費やしてしまいました。。。知っていれば何の問題もないのですが、 Session に気づくまでに時間がかかってしまいました。もしかするともっと良い方法があるのかもしれません。何れにしても同じ過ちを犯さないように注意してください。
» エンジニア登録はこちら