skip to Main Content

How can I optimize my Cloud Function to react to Firestore document status changes more efficiently? Is there a way to make this process event-driven rather than using periodic checks? I’m looking for a method that minimizes Firestore reads/writes and reduces the latency and costs associated with polling.
Imagine that I launch a program and two processes are initiated:

  1. The first process continuously checks if the status of a document has changed; if so, it stops the second process.
  2. The second process launches the logic.

This is an example below :

// Firestore Trigger to monitor document changes
exports.monitorDocument = functions.firestore
    .document('myCollection/myDocument')
    .onUpdate((change, context) => {
        // Check the updated document status
        const newValue = change.after.data();
        const oldValue = change.before.data();

        if (newValue.status !== oldValue.status) {
            console.log('Document status changed');
            // My logic
        }
    });

// Trigger to start the routine and manage the flow
exports.startRoutine = functions.https.onRequest(async (req, res) => {
    const docRef = admin.firestore().collection('myCollection').doc('myDocument');

    // Routine
    try {
        const doc = await docRef.get();
        if (doc.exists && doc.data().status === 'active') {

            // My logic

            // After the routine, check the document again before moving to 'Execution'
            const updatedDoc = await docRef.get();
            if (updatedDoc.data().status === 'active') {
                console.log('Proceeding to execution');
                // Next logic
            } else {
                console.log('Status changed, halting execution');
            }
        }
    } catch (error) {
        console.log('Error:', error);
    }

    res.send('Process completed');
});

Any insights or examples of using another logic, Firestore triggers, or other Google Cloud services to manage such workflows would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    [ANSWER] I found a way.

    I create a function subscribeToDocument().

    let yourObject = {};
    const unsubscribe = await subscribeToDocument(myDocumentId, yourObject);
    

    Then in the subscribeToDocument(), you will return a Promise, where there is a subscription to your document snapshot in it. You will pass the object with it, which you will use in your code to have real-time updates even during the execution of a loop.

    async function subscribeToDocument(myDocumentId, yourObject) {
        const docRef = db.collection('your-collection name').doc('myDocumentId');
    
        return new Promise((resolve, reject) => {
            const unsubscribe = docRef.onSnapshot((docSnapshot) => {
                if (docSnapshot.exists) {
                    const data = docSnapshot.data();
                    Object.assign(yourObject, data);
                    resolve(unsubscribe);
                } else {
                    reject(new Error("your error");
                }
            }, (error) => {
                unsubscribe();
                reject(error);
            });
        });
    }
    

    With this code, you will have real time update of your document during your program execution.

    Don't forget to unsubscribe(); when you finish the execution.


  2. Is there a way to make this process event-driven rather than using periodic checks?

    Cloud Functions for Firebase are indeed event-driven and will always fire in response to events that happen in the Firebase products, like Firebase Authentication, Cloud Firestore, the Realtime Database or Cloud Storage.

    I’m looking for a method that minimizes Firestore reads/writes and reduces the latency and costs associated with polling.

    Cloud Functions for Firebase don’t poll unless you write code in them that does polling.

    Seeing your code, I can say that the first function will fire when a matching document is updated, while the second one will fire when it is explicitly invoked via HTTP.

    When it comes to speed, I think that most likely you’re experiencing a so-called cold start of the function. For more info, please see check the r resource below:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search