Firebase functions logging does not work from non-callable functions - firebase

I'm getting started with Firebase Functions. I made a simple callable function:
exports.myCallable = functions.https.onCall((data, context) => {
console.log('I am here.');
functions.logger.log('I am here 2.');
});
As expected, I see these logs in the Logs tab in Firebase Console.
However, I also made this function, which should trigger when the user creates their account.
exports.setGroupAfterAuth = functions.auth.user().onCreate((user) => {
console.log('I am here 3.');
functions.logger.log('I am here 4.');
});
In this case, I see that the function was called in Firebase Console, but I do not see my logs.
Why do the logs appear in Firebase Console for the first function but not the second, and what can I do to make them appear in the second?

It's not possible to use the Firebase Functions client SDK to invoke an auth onCreate function.
Auth onCreate functions can only be invoked by actually creating a new user account. They cannot be invoked directly from your app.
The client SDK can only be used to invoke callable functions, as described in the linked documentation. The funciton must be declared with functions.https.onCall.

Related

Some Cloud Functions formats are not deployed

I guess it must be a silly reason but I don't understand why from these 2 Cloud Functions, only the first one is recognized and deployed when I run the following command:
firebase deploy --only "functions:test1,functions:test2"
The first function that is a simple CRON is well deployed:
exports.test1 = functions
.pubsub.schedule('2,7,12,17,22,27,32,37,42,47,52,57 * * * *')
.timeZone('Europe/Paris')
.onRun((context) => {
console.log('test1');
});
The second one that receives data from a PubSub is never deployed:
exports.test2 = (message, context) => {
const name = message.data
? Buffer.from(message.data, 'base64').toString()
: 'World';
console.log('test2');
};
Do I have to use the gcloud commands to deploy the second one?
The second function test2 which receives data from Pub/Sub is triggered by a Pub/Sub topic. Cloud Functions for Firebase with Pub/Sub trigger which you can find here. As per the linked documentation you should mention the Cloud Functions for Firebase to be triggered by the Pub/Sub topic inside the functions code. The firebase deploy command does not have an option to specify the trigger topic while running the command. So if you want to deploy both the functions at a time then you should change your code to include the trigger topic as following -
exports.test2 = functions.pubsub.topic('topic-name').onPublish((message) => {
const name = message.data
? Buffer.from(message.data, 'base64').toString()
: 'World';
console.log(name);
});
topic-name is your Pub/Sub topic name.
If you don’t want to deploy both the functions at a time, then you can deploy the test2 function using gcloud with the code you have written and specify the trigger topic name while running the command, as mentioned here.

How to trigger Pub/Sub Topic for Firebase Emulator

Using Firebase Functions, I have code that runs every hour via a Google Cloud Scheduler Job.
It looks like this:
exports.hourly_tick =
functions.pubsub.topic("hourly-tick").onPublish((message, context) => {
return getData()
.then((data) => {
sendEmail(data["message"]);
})
.catch((error) => {
return console.log("🚩 Caught error: ", error);
});
});
I need to be able to test this locally, and am able to start my Firebase Emulator via firebase emulators:start from my terminal. However I do not know how to trigger this function in my local test environment to see logs in the local emulator.
How can I test this scheduled job / firebase function with the local emulator?
This is an ongoing feature request in Firebase tools (see GitHub issue).
As mentioned in the thread:
I think we maybe misled with how we represented #2011. It lets those functions be loaded into the emulator but doesn't actually trigger them on a schedule. Instead you'd have to manually trigger them using a Pub/Sub message.
You can check a workaround on this answer where you'd have to manually trigger a scheduled function using a Pub/Sub message.

Deploying Cloud Firestore Trigger function from GCP Console

I have a function that is fired on a onUpdate trigger from my cloud firestore database.
The function not being called at all when I change my database.
I did not deploy the function using firestore CLI, instead I deployed it using the GCP Console.
Here is the function:
exports.NotificationListener = functions
.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const userId = context.params.userId.toString();
const eventId = context.eventId;
console.log('EventId:' + eventId);
console.log('Change in:' + userId);
return 200;
});
Here is the deployment information from the GCP console (showing the trigger):
Finally, here is the Cloud Firestore schema:
I want to monitor any changes to any "USER" in the collection: "/user", hence I am using "user/{userId}".
Why is this function not being called when I change the database ?
EDIT 1
A little information about my environment:
I have my entire project core in a TypeScript file. I have over 40 HTTPS triggered functions that are currently online.
I add a new function in my TS file, then I do a npm run build to compile and get the JS file.
Finally, I go to Google Cloud Console and create a function and choose "Zip Upload" and upload the compiled JS file (obviously, along with the required JSON files for getting Database URL, Authentication etc.)
This approach works perfectly fine, at least for HTTP triggered firestore functions.
Now I repeated the same steps as above for the onUpdate trigger and just instead of choosing HTTP trigger, I chose Cloud Firestore trigger. The trigger information can be found above in the screenshot.
onUpdate is not being fired on DB changes.
EDIT 2
My event trigger function NotificationListener is showing up in the firebase console functions list along with my other 40 HTTPS functions. But it is not being called.
#doug-stevenson, your answer seems to have disappeared, I am not sure why.
Anyway, I found the reason why it wasn't working.
My firebase database was in project "Placeholder 1" and my GCP functions were in project "Placeholder 2".
Now, I was able to update the "Placeholder 1" DB from GCP functions (in "Placeholder 2") using firabse-functions API because I set the DatabaseURL to "Placeholder 1".
But, just setting the DatabaseURL to the desired database doesn't work if you want to LISTEN to the database for changes. You actually need to have the function in the same project otherwise it is not able to subscribe and listen for events.
I think it's a little inconsistent that you can read/write to a DB from different projects, but to listen for events, function needs to be in same project.
Or maybe I am missing something fundamental that caused this confusion for me.

Cloud Functions: callback is not a function

According to https://cloud.google.com/functions/docs/writing/background
You use background functions when you want to have your Cloud Function invoked indirectly in response to an event, such as a message on a Cloud Pub/Sub topic, a change in a Cloud Storage bucket, or a Firebase event.
And the function paramaters are (data, context, callback): https://cloud.google.com/functions/docs/writing/background#function_parameters
However, when I write a simple function like
exports = module.exports = functions.firestore
.document(path)
.onWrite((change, context, callback) => {
callback()
return
})
I get an error that says
TypeError: callback is not a function
Is callback not part of Firestore background functions? The documentation says it is
If not, is there anyway to immediately exit a function?
The Firebase API is different than the Google Cloud API. What you linked to was the Cloud API, which accepts a callback parameter. The Firebase API which you are actually using does not. The Firebase API for background functions requires you to return a promise that resolves after all the work is complete. There is no callback to call in that case.

Firebase: Writing Custom Callable Cloud Function vs Cloud Firestore Trigger Function

I learned all about Google Cloud Functions Triggers and I understood that they are good for doing some data preprocessing before write/update/delete happens in Cloud Firestore. This is true right?
However, instead of listening to changes in the database, I would like to write custom code in Cloud Functions and call it directly from the client SDK.
The reason I want to do this is because I don't want to have long complicated database integration logic in my client code. I just want to call a cloud function named createGame for instance and let the custom cloud function handle the nested calls to the Firestore, do sanity checks and return me with only the clean data that the client will be displaying.
I found out that there is a Flutter plugin for this called cloud_functions.
Also this documentation shows how to write custom callable functions.
We can write the custom callable Cloud Function as follows:
exports.createGame = functions.https.onCall((data, context) => {
// ...
return {
...
}
});
We can call the corresponding custom callable Cloud Function from Flutter client as follows:
final dynamic response = await CloudFunctions.instance.call(
functionName: 'createGame',
parameters: <String, dynamic>{
'message': 'hello world!',
'count': clientCount,
},
);
There are tons of Cloud Functions trigger examples/videos/tutorials. But very few of callable Cloud Functions. That's why I am a little skeptic about this subject.
Question:
My question is if this is good practice? Or should I do what this specific Cloud Function is doing from the client? Please answer while keeping pricing, speed, reliability and other factors in mind also:)
One last thing,
The function implementation uses https.onCall. Do you think https is slowing things down?

Resources