I have a Google Cloud maintenance function I wish to run to update a Firebase Real-time Database. The code is pretty straight forward, but for some reason the execution finishes before all code is run. I suspect that my await call is not handled as expected because I am miss-using .once()?
exports.setUserLimits = functions
.region('europe-west1')
.database
.ref('/NO-TRIGGER')
.onCreate(async (snapshot, context) => {
let myPromises = []
const userNodeSnap = await database.ref('users').once('value')
console.log('numChildren', userNodeSnap.numChildren())
userNodeSnap.forEach(async (userSnap) => {
console.log('Process user', userSnap.key)
const userData = userSnap.val()
//Set user limits
const limits = {items:10, logins:1}
console.log('New limits', limits)
myPromises.push(userSnap.ref.update({limits}))
})
// Execute all promises
console.log('myPromises lenght', myPromises.length)
return Promise.all(myPromises)
.then(()=>{
return Promise.resolve()
})
.catch((err)=>{
console.error('Could not execute all promises', err)
// Show must go on!
return Promise.resolve()
})
})
Logout from Google Cloud Functions
setUserLimits Function execution started
numChildren 4
Process user 1234567890
myPromises lenght 0
Function execution took 416 ms, finished with status: 'ok'
New limits {items:10, logins:1}
The execution finishes prematurely resulting in only one record being updated.
Replacing the last lines to below generates the same result
await Promise.all(myPromises)
/K
If we look at this block of code:
userNodeSnap.forEach(async (userSnap) => {
console.log('Process user', userSnap.key)
const userData = userSnap.val()
//Set user limits
const limits = {items:10, logins:1}
console.log('New limits', limits)
myPromises.push(userSnap.ref.update({limits}))
})
we see that it has the logical form:
someArray.forEach(async function(element) {
// do something
});
Basically, code after the forEach
function call can execute before the completion of processing of each element of the aray.