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)))