Home > Mobile >  Extremely Slow Google Cloud Function (1 minute )
Extremely Slow Google Cloud Function (1 minute )

Time:07-13

I have a Google Cloud Function to handle username and profile picture changes in my firestore database. Whenever a user updates their profile picture or name, a cloud function updates all their reviews so they match the new data. However, this function is taking over a minute to run, even though I only have a single review in the database.

Why is this happening and is there a more efficient way to perform this update?

exports.onProfilePictureOrNameChange = functions.firestore
.document("userProfiles/{userProfileId}")
.onUpdate(async (change, context) => {
    const userNamebefore = change.before.data().usePreferredName ? change.before.data().preferredName : change.before.data().fullName;
    const userNameAfter = change.after.data().usePreferredName ? change.after.data().preferredName : change.after.data().fullName;
    const nameChanged = userNamebefore !== userNameAfter;
    const profilePictureChanged = change.after.data().profilePictureURL !== change.before.data().profilePictureURL;

    if (nameChanged || profilePictureChanged) {
        const data = {
            profilePictureURL: change.after.data().profilePictureURL,
            userName: userNameAfter,
        };

        afs.collection("reviews").where("userProfileId", "==", change.after.id).get().then(function(querySnapshot) {
            querySnapshot.forEach(function(doc) {
                doc.ref.update(data);
            });
        });
    }
});

CodePudding user response:

You're not returning anything from the top-level code in your Cloud Functions, which means that the container has no way to know when the code is done.

To make it work correctly, return a promise from the top-level code that resolves when all asynchronous work is done. And as Dharmaraj commented, you'll need to use Promise.all to signal the completion of the nested writes in the loop.

So something like:

exports.onProfilePictureOrNameChange = functions.firestore
.document("userProfiles/{userProfileId}")
.onUpdate(async (change, context) => {
    const userNamebefore = change.before.data().usePreferredName ? change.before.data().preferredName : change.before.data().fullName;
    const userNameAfter = change.after.data().usePreferredName ? change.after.data().preferredName : change.after.data().fullName;
    const nameChanged = userNamebefore !== userNameAfter;
    const profilePictureChanged = change.after.data().profilePictureURL !== change.before.data().profilePictureURL;

    if (nameChanged || profilePictureChanged) {
        const data = {
            profilePictureURL: change.after.data().profilePictureURL,
            userName: userNameAfter,
        };

        return afs.collection("reviews").where("userProfileId", "==", change.after.id).get().then(function(querySnapshot) {
            const promises = querySnapshot.docs.nap((doc) => {
                return doc.ref.update(data);
            });
            return Promise.all(promises);
        });
    }
});

I strongly recommend checking out the documentation on sync, async and promises and the video series linked in there, as it pays to understand how asynchronous behavior affects execution of your Cloud Functions.

  • Related