Reputation: 691
The code below scans all users looking for nodes to be archived: function archiveColab()
The problem is that the function is inside a forEach that scans the /users/ node and then needs to scan the /collaborative child, so it has another forEach inside.
When I run the arquivaColab function it overwrites the daily records in the monthly without counting the total of each cycle, leaving only the last cycle for that month.
This is due to asynchronous execution forEach and I'm not able to find a way to sequentially read and write these records.
When adding await/promisse, apparently the cycle ends after executing the first cycle/record.
I understand that this is a problem with understanding how asynchronous mode works and I have been trying to find a solution for a few days.
Any help would be very welcome.
CODE:
exports.todoDia = functions.runWith({memory: '1GB', timeoutSeconds: '300'}).pubsub.schedule('10 15 * * *').timeZone('America/Sao_Paulo').onRun( async () => {
const cutoff = format(new Date().setDate(new Date().getDate() - 7), 'Y-m-d'); // 7 days ago
var userRef = admin.database().ref("users");
return userRef.once('value').then((snapshot) => {
snapshot.forEach(user => {
var userID = user.key;
if (userID === "F54jCdsPt8ZLIF17dYn8U0knMMY2") { // Only this user for testing
console.log(userID + " " + cutoff);
user.child('collaborative').forEach(async collaborative => {
if (collaborative.key <= cutoff) { await arquivaColab(userID, collaborative.key, collaborative.val()); }
});
}
});
return null;
});
});
async function arquivaColab(userID, keyColab, valColab) {
console.log("userID: "+userID+" | keyColab: "+keyColab+" | valColab: "+valColab);
const ref = admin.database().ref("/collaborative/"+userID+"/"+keyColab.substring(0,7));
var stringDest = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
return ref.once('value').then((snapDest) => {
if (snapDest.exists()) { stringDest = snapDest.val() }
var wordsOrig = valColab.split(" ");
var wordsDest = stringDest.split(" ");
var strFinal = "";
for (var i = 0; i < wordsOrig.length; i += 1) {
strFinal += (Number(wordsOrig[i]) + Number(wordsDest[i])) + " ";
}
console.log("DESTINO: /collaborative/"+userID+"/"+keyColab.substring(0,7)+" : "+strFinal);
return admin.database().ref("/collaborative/"+userID+"/"+keyColab.substring(0,7)).set(strFinal.trim());
// console.log("ORIGEM : /users/"+userID+"/collaborative/"+keyColab+" : "+valColab);
// admin.database().ref("/users/"+userID+"/collaborative/"+keyColab.set(null);
});
}
JSON:
"users" : {
"F54jCdsPt8ZLIF17dYn8U0knMMY2" : {
"collaborative" : {
"2021-03-12" : "0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0",
"2021-03-15" : "0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0",
"2021-07-07" : "0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0"
},
"username" : "John Doe"
},
"Z5EEkzyG2WPlCHa9a6gDpBnIr2u2" : {
"collaborative" : {
"2021-07-06" : "0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0",
"2021-07-07" : "0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0"
},
"username" : "John Next"
},
},
To understand the desired functioning: Each user has a node called "collaborative"
YYYY-MM-DD : "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
There are 20 counters that record different activities of each user on a daily basis. After 7 days Firebase Functions must archive these records counting the sum of each counter in a monthly record in /collaborative/userID/.
Upvotes: 0
Views: 282
Reputation: 7418
forEach
does not support async/await
. You would need to store the data into an array and use a for
loop that supports async/await
like here:
return userRef.once("value").then(async (snapshot) => {
const tempArray = [];
if (userID === "F54jCdsPt8ZLIF17dYn8U0knMMY2") {
// Only this user for testing
console.log(userID + " " + cutoff);
user.child("collaborative").forEach(async (collaborative) => {
if (collaborative.key <= cutoff) {
tempArray.push({
userID,
key: collaborative.key,
val: collaborative.val(),
});
}
});
}
for (let i = 0; i < tempArray.length; i++) {
const { userID, key, val } = tempArray[i];
await arquivaColab(userID, key, val);
}
});
return null;
Upvotes: 1