Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Too much delay in the completion of the cloud function

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");
                });
            });
          });
      });
    }
  });
like image 234
Bilal Saeed Avatar asked Sep 15 '25 04:09

Bilal Saeed


1 Answers

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 than for()

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:

  • Why is my Cloud Firestore query slow?
  • The Firebase Blog: Keeping our Promises (and Callbacks)
like image 113
Rogelio Monter Avatar answered Sep 17 '25 19:09

Rogelio Monter