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:
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.
[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.