This is the cloud function that I'm using to send notification to the shopkeepers when an order is accepted by the shipper. But sometimes it takes at least 20 seconds to complete and more often take more than 3 minutes. My other cloud functions are working completely fine. Can't figure out the issue with this function.
exports.onChangeOfOrderStatus = functions.firestore
.document('orders/{documentId}')
.onUpdate(async (change, context) => {
// Get an object with the current document value.
// If the document does not exist, it has been deleted.
const document = change.after.exists ? change.after.data() : null;
// Get an object with the previous document value (for update or delete)
const oldDocument = change.before.data();
const newDocument = change.after.data();
const oldStatus = oldDocument.orderStatus;
const newStatus = newDocument.orderStatus;
functions.logger.log(oldStatus);
functions.logger.log('TO');
functions.logger.log(newStatus);
let orderPassed = false;
let shopsIds = [];
Array.prototype.push.apply(shopsIds, newDocument.shopsWhoGotOrders);
functions.logger.log("Printing shopIds 1st time");
shopsIds = getUnique(shopsIds);
printArray(shopsIds); //Code works fine and instantly at this point of line
let shopTokensAre = [];
if (oldStatus == 'prepending' && newStatus == 'pending') {
shopsIds.forEach(async result => {
await admin.firestore().collection("users")
.where('role', "==", 'shopkeeper')
.where('uid', '==', result)
.get().then(snapshot => {
snapshot.forEach(async doc => {
shopTokensAre.push(doc.data().token);
functions.logger.log("Printing shopIds: 2nd time"); // This line
//takes time to print
functions.logger.log(doc.data().token);
await admin.messaging().send({
token: doc.data().token,
notification: {
title: "Hi TELLOO Shopkeeper",
body: 'You received a new order, Please Accept/Reject it fastly',
imageUrl: 'https://support.kraken.com/hc/article_attachments/360085484571/ProApp_NewOrderButton_02082021.png',
}
})
.then(snapshot => {
functions.logger.log("Notifications sent");
});
});
});
});
}
});
As I see, your code it runs well until you have to query the data and do some process on it.
Nested .forEach
are making your code slower, so it could be a good idea to change them with for()
loops, as pointed here.
Array.ForEach
is about 95% slower thanfor()
Also, you should use Javascript promises to terminate your function properly, as stated in the official documentation:
By terminating functions correctly, you can avoid excessive charges from functions that run for too long or loop infinitely. ... Use these recommended approaches to manage the lifecycle of your functions:
- Resolve functions that perform asynchronous processing (also known as "background functions") by returning a JavaScript promise
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With