Lors de l'écriture de fonctions cloud basées sur des événements pour Firebase Firestore, il est courant de mettre à jour les champs dans le document concerné, par exemple:
Lorsqu'un document de la collection d'utilisateurs est mis à jour, une fonction se déclenche, disons que nous voulons déterminer l'état des informations utilisateur et que nous avons une propriété completeInfo: boolean
, la La fonction devra effectuer une autre mise à jour pour que le déclencheur se déclenche à nouveau, si nous n'utilisons pas un indicateur comme needsUpdate: boolean
pour déterminer si en exécutant la fonction, nous aurons une boucle infinie. p >
Existe-t-il une autre façon d'aborder ce comportement? Ou la situation est-elle une conséquence de la façon dont la base de données est conçue? Comment éviter de se retrouver dans un tel scénario?
3 Réponses :
Vous devez faire attention à ne pas écrire une fonction qui se déclenche indéfiniment. Ce n'est pas quelque chose que Cloud Functions peut faire pour vous. En règle générale, vous effectuez cette opération en vérifiant dans votre fonction si le travail a été effectué précédemment pour le document qui a été modifié lors d'un appel précédent. Il existe plusieurs façons de procéder, et vous devrez mettre en œuvre quelque chose qui correspond à votre cas d'utilisation spécifique.
Ce que vous dites à propos de vérifier si le travail a été effectué précédemment est ce que fait la propriété needsUpdate
dans l'exemple que j'ai partagé, mais quelles sont les pratiques recommandées par les développeurs de firebase?
Comme je l'ai dit, il existe de nombreuses façons de le faire, et vous devez faire ce qui convient à votre cas d'utilisation. La meilleure pratique consiste simplement à faire tout ce qu'il faut pour satisfaire votre cas d'utilisation.
Pourriez-vous fournir des exemples de cas et des techniques / moyens de le faire? Ou probablement les référencer?
Je prendrais cette approche du point de vue du temps d'exécution, cela signifie que la fonction de chaque document sera exécutée deux fois. Chaque fois que le document est déclenché, un champ lastUpdate
serait là avec un horodatage et la fonction ne met à jour le document que si l'heure est plus ancienne que mon heure - par exemple 10 secondes.
Je n'aime pas vraiment cette approche, compter sur le temps n'est pas si judicieux lorsque plusieurs fonctions peuvent s'exécuter en même temps.
J'ai quelques approches courantes des fonctions Cloud Functions qui transforment les données:
Écrivez les données transformées dans un document différent de celui qui déclenche la fonction cloud. C'est de loin l'approche la plus simple, car il n'y a pas de code supplémentaire nécessaire - et donc je ne peux pas faire d'erreur. Cela signifie également qu'il n'y a pas de déclencheur supplémentaire, donc vous ne payez pas pour cette invocation supplémentaire.
Utilisez des déclencheurs granulaires pour vous assurer que ma fonction Cloud ne sera appelée que lorsqu'elle a réellement besoin de travailler. Par exemple, beaucoup de mes fonctions ne doivent être exécutées que lorsque le document est créé, donc en utilisant un déclencheur onCreate
, je m'assure que mon code n'est exécuté qu'une seule fois, même s'il finit par mettre à jour le document nouvellement créé .
Ecrivez les données transformées dans le document existant. Dans ce cas, je m'assure de vérifier si la transformation est nécessaire avant d'écrire le code réel de la transformation. Je préfère ne pas ajouter de champs d'indicateur, mais utiliser les données existantes pour cette vérification.
Un exemple récent est celui où je mets à jour un montant dans un document, qui doit ensuite être ventilé à tous les utilisateurs:
exports.fanoutAmount = functions.firestore.document('users/{uid}').onWrite((change, context) => { let old_amount = change.before && change.before.data() && change.before.data().amount ? change.before.data().amount : 0; let new_amount = change.after.data().amount; if (old_amount !== new_amount) { // TODO: fan out to all documents in the collection } });
J'aime vos approches, cela m'a donné une idée de créer une collection appelée operations
à l'intérieur des entités de document comme user
, en enregistrant quelques configurations de base dans le document d'entité et les sous-collections pour chaque opération comme create
, updatePermissions
, etc ...