Call Cloud Function from another Cloud Function [duplicate] - node.js

Firestore Cloud Functions priority
Now I deploy two cloud functions in the Firestore database.
They are triggered by the same document changes.
Is it possible to specify the execution order of the functions or the trigger sequence? For example, I want to let updateCommentNum function trigger fist, then trigger writeUserLog function. How could I achieve this goal?
exports.updateCommentNum = functions.firestore
.document('post/{postId}/comments/{commentsID}')
.onWrite((change, context) =>
{
//update the comment numbers in the post/{postId}/
}
exports.writeUserLog = functions.firestore
.document('post/{postId}/comments/{commentsID}')
.onWrite((change, context) =>
{
//write the comment name,text,ID,timestamp etc. in the collection "commentlog"
}

There is no way to indicate relative priority between functions.
If you have a defined order you want them invoked in, use a single Cloud Function and just call two regular functions from there:
exports.onCommentWritten = functions.firestore
.document('post/{postId}/comments/{commentsID}')
.onWrite((change, context) => {
return Promise.all([
updateCommentNum,
writeUserLog
])
})
function updateCommentNum(change, context) {
//update the comment numbers in the post/{postId}/
}
function writeUserLog(change, context) {
//write the comment name,text,ID,timestamp etc. in the collection "commentlog"
}
That will also reduce the number of invocations, and thus reduce the cost of operating them.

Related

Number of reads for multiple Firebase trigger functions doing similar things

I have an onUpdate firestore trigger function that does multiple things:
functions.firestore.document('document').onUpdate((change, context) => {
const updatedObject = change.after.data()
if (updatedObject.first) {
doFirst()
}
if (updatedObject.second) {
doSecond()
}
})
I am thinking of splitting this trigger into 2 smaller triggers to keep my functions more concise.
functions.firestore.document('document').onUpdate((change, context) => {
const updatedObject = change.after.data()
if (!updatedObject.first) {
return
}
doFirst()
})
functions.firestore.document('document').onUpdate((change, context) => {
const updatedObject = change.after.data()
if (!updatedObject.second) {
return
}
doSecond()
})
The firestore pricing docs mentions the following:
When you listen to the results of a query, you are charged for a read each time a document in the result set is added or updated. You are also charged for a read when a document is removed from the result set because the document has changed. (In contrast, when a document is deleted, you are not charged for a read.)
Would this increase the number of reads from 1 to 2?
The docs does not clearly state the behavior when there are multiple functions listening to the same event.
A more general question I have is would increasing the number of functions listening to the same event increase the number of reads and hence increase my bill?
Is there a best practice for this issue?
firebaser here
The document data passed to Cloud Functions as part of the trigger (so change.before and change.after) comes out of the existing flow, and is not a charged read. Only additional reads that you perform inside your Cloud Functions code would be charged.

Firebase Cloud Functions common functions not updated for when single function is deployed

I have multiple Firebase cloud functions which are calling some local common functions as per the following structure.
export const f1Delete = functions.firestore.document("col1/{doc1ID}").onDelete(async (snap, context) => {
...
reportDeleted(1);
});
export const f2Delete = functions.firestore.document("col2/{doc2ID}").onDelete(async (snap, context) => {
...
reportDeleted(2);
});
async function reportDeleted(n: number) {
...
}
Now, I updated the common function reportDeleted. When I deploy f1Delete and checked the files in gCloud the change is done for only function f1Delete. Function f2Delete still shows the old code.
Do I need to deploy all functions using the common method in this case to make the changes happen for all functions?
Yes, you need to deploy every function. If you deploy only function1 then only that will be getting update helper function.

How can I have multiple Firebase Database listeners and `exports.pushNotification` in Firebase Functions

I have a listener that pushes notifications when a change happens in the Firebase Realtime Database.
exports.pushNotification = functions.database
.ref("/Currency/Price")
.onWrite((change, context) => { ... }
I tried just copying the same function shown above and just changing the database reference, but it just ended up disregarding the first one, so only the second database reference pushes notifications, and not the first.
How can I add another listener and push notification for another record in the Realtime database?
If you want to declare two different Cloud Functions that should be triggered on the same database location (i.e. node), just use another name, as follows:
exports.pushNotification1 = functions.database
.ref("/Currency/Price")
.onWrite((change, context) => { ... }
exports.pushNotification2 = functions.database
.ref("/Currency/Price")
.onWrite((change, context) => { ... }
If you want to declare another function but on another location, just do as follows:
exports.pushNotification1 = functions.database
.ref("/Currency/Price")
.onWrite((change, context) => { ... }
exports.pushNotification2 = functions.database
.ref("/abcd/efgh")
.onWrite((change, context) => { ... }

Is it possible to return data before the end of the onCall function in Firebase Cloud Functions

I would like to know if it's possible to return data before my onCall function finish.
Here is what I'm trying to do and my result data in my app is always equal to null:
exports.myFunction = functions.https.onCall((data, context) => {
if (!context.auth || !context.auth.uid) {
return {
statut: "NOK",
};
}
return Promise.all([promise1(), promise2()])
.then(results => {
const result1 = results[0].data();
return FIRESTORE.collection('MyCollection')
.add(result1)
.then(results2 => {
let queries = [];
queries.push(
function1234()
);
queries.push(
FIRESTORE.collection('MyCollection2')
.doc("123")
.set({a: 123})
);
return Promise.all(queries)
.then(r => {
return { myReturn: "AAAA" };
});
})
.then(r2 => {
console.log('0000');
return function9898();
})
})
this is my client side function:
myFunction = () => {
var myFunctionCloud = firebase.functions().httpsCallable('myFunction');
myFunctionCloud().then(function (result) {
console.log(JSON.stringify(result));
})
}
My logs :
{"data":null}
I would like to know if it's possible to return data before my onCall
function finish.
No, it is not possible since returning data in a Callable Cloud Function indicates to the Cloud Functions platform that the Callable Cloud Function is finished and that it can clean up everything from that invocation. So in many cases, your Cloud Function will be terminated before your business logic is fully executed.
In some cases, it may be possible that the Cloud Functions platform does not terminate your CF immediately, giving enough time for your business logic to be fully executed, but this is not at all guaranteed. Relying on this specific case is not recommended and actually leads to some "erratic" behaviour
One of the approach to immediately send back a result to the front-end and continue to work in the background is to call a PubSub Cloud Function (with all the relevant input in the message) and then return the value. In other words, you delegate the remaining work to another Cloud Function and you stop the current Callable one by returning a response.

onWrite in Multiple Database in one Firebase Project

I have a firebase project which has one default database and 3 other databases which I have created. I understand that each of these database contain a different URL which can be used to trigger cloud functions.
All the 3 database have a path /ref/user/message. Now in my Index.JS file I want to create a function which performs onWrite if there's an update performed on the above path from any of the database. Also, I would want to know which database instance has been updated.
You will have to write one function for each of the database instances, but you can pretty easily share common code between them by having them all call a common function.
exports.db1 = functions.database.instance('db1').ref('/your/path').onWrite((change,context) => {
return onWrite('db1', change, context)
})
exports.db2 = functions.database.instance('db2').ref('/your/path').onWrite((change,context) => {
return onWrite('db2', change, context)
})
function onWrite(instance, change, context) {
// your code here
return some_promise
}

Resources