Google Cloud Functions で Firestore appsをイニシャライズしようとするとValueErrorになってしまう。


困ったこと

Google Cloud Functionsで、あるデータを取得してFirestoreに保存するという処理を作成し、
Cloud Schedulerで数分置きに動作するようにしました。

ローカル環境からもクラウドでの実行テストもOKでしたが、いざスケジュール実行すると、
以下のように、実行結果のステータスが'ok'と'crash'を繰り返すようになりました。

環境

  • Google Cloud Functions
  • Firestore
  • Python3.7

当初の実装

公式の解説の通りに実装

こう記載するだけで、同じアカウント内でFirestoreにアクセスできるみたい。簡単にできた!

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# Use the application default credentials
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
  'projectId': project_id,
})

db = firestore.client()

しかし、いざスケジュールに乗っけると冒頭の現象に。。

エラーの内容を調べてみると、以下のValueErrorが吐かれていました。

ValueError: The default Firebase app already exists. 
This means you called initialize_app() more than once without providing an app name as the second argument.

initialize_app()を2回呼ぶなと怒られているようだ。
コードを見直してもみたが、一回の実行の中では一度しか呼んでないはず。。。

解決した実装

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

if not firebase_admin._apps:
  cred = credentials.ApplicationDefault()
  firebase_admin.initialize_app(cred, {
    'projectId': project_id,
  })

db = firestore.client()

stack overflowで同じエラーで困っている人がいたので、それを参考に。
単純ですが、すでにApplicationを初期化済みかどうかチェックをするif文を入れることで解決しました。

Cloud FunctionsとCloud Schedulerの動きがよくわかっていませんが、
時間を空けずに実行すると前の実行で生成されたインスタンスを再利用するような動きなんだろうか。

ローカルでは連続で実行しても何の問題もなかったので、ハマってしまいました。