Cloud Functions用Cloud Firestoreトリガーは、1回**"以上"**呼ばれる可能性があり、複数回呼ばれても大丈夫な設計が求められます。
※ PUSH通知を書く処理を書いていたとして2回呼ばれたら2回通知が飛んでしまいますね。
イベントは必ず 1 回以上処理されますが、1 つのイベントで関数が複数回呼び出される場合があります。「正確に 1 回」のメカニズムに依存することは避け、べき等になるように関数を記述してください。
https://firebase.google.com/docs/functions/firestore-events
Idempotent (べき等)については、こちらもご参考までにです。
何度呼ばれても結果がおなじになるように、ぐらいの意味ですね。
https://developer.mozilla.org/ja/docs/Glossary/Idempotent
さて、べき等にするためのヒントはこちらの資料にあります。
https://cloud.google.com/blog/products/serverless/cloud-functions-pro-tips-building-idempotent-functions
上記の資料によると eventId を使用すると良さそうですね。
export const notifyToAdmin = functions.firestore
.document('articles/{articleID}')
.onCreate(async (snap, context) => {
console.log(context.eventId)
})
このeventIDを1回目の処理の際にFirestoreに保存しておき
2回目以降はその値があると処理をやめるようにすると良さそうですね。
さて!今回、気になりましたのは
export const notifyToAdmin = functions.firestore
.document('articles/{articleID}')
.onCreate(async (snap, context) => {
console.log("notifyToAdmin:", context.eventId)
})
export const notifyToUsers = functions.firestore
.document('articles/{articleID}')
.onCreate(async (snap, context) => {
console.log("notifyToUsers:", context.eventId)
})
このように同じドキュメントの変更に対してトリガーを設定した場合に
eventIDが違うものになるかということです。
もしおなじになってしまえば、先ほどの対応策は間違いということになります。
結果のログはこの様になりました。
途中までIDは一緒ですが最後の数字で区別しているようですね!
このようなケースでも、eventIDを利用して、べき等になるような関数を作ることが出来ることが確認できました。
最後にeventIDをUniqueでFirestoreに書き込む際の参考記事をご紹介します。
eventIDが保存されるのが必ず1回とすることにより関数が2回実行されてしまうことを防ぐことが出来ます。
Cloud FirestoreでUniqueを実現する2手法とその使い分け