Home > Software design >  How to properly write cloud functions that automatically update firestore documents
How to properly write cloud functions that automatically update firestore documents

Time:12-12

I am trying to write a firebase cloud function that runs a simple while loop every time a new user creates an account. For some reason, the update function only runs once and stops. The code i use is pasted below

const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();
var data;
var counter = 0;


 exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
   data = snapshot.data();
   while (counter < 5) {
    setInterval(updateCounter(counter), 5000);
  }
  
 })

 async function updateCounter(counter){
  await firestore.collection('testCollection').doc(data['username']).update({
    counter: admin.firestore.FieldValue.increment(1)
  });
  counter  ;
 }


CodePudding user response:

Cloud Functions stops running your code when it hits the final } of your function, as otherwise it'd be billing your indefinitely for it.

If you want your code to continue running, you'll need to return a promise that resolves when your code is done with its work (up to 9 minutes).

exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
  data = snapshot.data();
  return Promise((resolve, reject) => {
    while (counter < 5) {
      setInterval(updateCounter(counter), 5000);
    }
    setInterval(() => {
      if (counter >= 5) {
        resolve()
      }
    }, 5000)
  })
})

Note that the while (counter < 5) loop in the code still won't do what you expect it to do, but at least now the function will continue to run for a few moments and the counter will be incremented.


This is probably what you want:

exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
  data = snapshot.data();
  return Promise((resolve, reject) => {
    setTimeout(updateCounter,  5000);
    setTimeout(updateCounter, 10000);
    setTimeout(updateCounter, 15000);
    setTimeout(updateCounter, 20000);
    setTimeout(updateCounter, 25000);
    setInterval(() => {
      if (counter >= 5) {
        resolve()
      }
    }, 5000)
  })
})

This calls updateCounter 5 times, each 5 seconds after the previous call. There is a chance that the final database update won't be completed before the call to resolve, so I strongly recommend learning more about asynchronous behavior by reading the documentation on sync, async, and promises and watching Doug's excellent promises and async behavior in Cloud Functions series.

CodePudding user response:

if the requirement is to run this function 5 times, once every 5 seconds, this could work.

for (let i =0;i<5;i  ){
  await updateCounter();
  await sleep (5000);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
  • Related