Google firebase database with google functions running locally - firebase

I have an app connected to google firebase realtime database. I want to test google cloud functions as a server for running backend functions triggered once every day or triggered by data changed in the database.
I have an emulator instance running locally with a typescript function that I wrote.
I have the realtime database running, connected to the app and working well.
Now when I change data in the database, the functions are not being triggered.
function in index.ts:
import * as functions from "firebase-functions";
exports.simpleDbFunction = functions.region('europe-west1').database.ref('/some path in the database')
.onCreate((snap, context) => {
console.log("functions triggered by datachange:", snap.val())
});
the firebase project is connected to the correct project (using the interface in the terminal).
the app and realtime database are currently working and I can see changes in the data inside the firebase console.
What am I missing?
I've also tried the more complicated example from google's documents (makeUppercase function). But when it didn't work I went back to a simple function that is triggered on data creation and prints to the console.
Edit: I notice that in the emulator UI the real time database is empty. Shouldn't it connect to the real time database of the app? isn't that why I connected the emulator to a specific project?
Edit2: I tried changing the function line to:
functions.region('europe-west1').database.instance("the URL of the
rtdb").ref(...
and I get an error saying that the event function has malformed resource member

So I kinda solved it:
I found out that you can't really connect from a local emulator to the production environment of your actual google firebase. (Which is kinda weird, you have to commit to this technology even before you had a chance to see any code in action) <-- fix me if I'm wrong about this
If you use realtime database cloud functions you can't use any region other than 'us-central1'. as mentioned in this document:
https://firebase.google.com/docs/functions/locations
You can connect your app to the local emulator on your machine!
Get your database instance:
FirebaseDatabase database = FirebaseDatabase.getInstance();
Add the following line in your app (which is weird) before the first database operation:
database.useEmulator("10.0.2.2", 9004);
change 9004 to your local realtime database port.

Related

Firebase cloud functions emulators always write to a default database

I recently set up the firebase emulators to run my cloud functions locally. After setup, the cloud functions triggered successfully but any write to the real-time database does not reflect in the corresponding local database emulator UI. e.g when I use
snapshot.after.ref.parent.child('busy').set(true)
So I tried exporting and importing the real-time data and I discovered that all database write from cloud functions was being saved in a default database with name localhost:4000/?ns=pick2-c468b-default-rtdb and not the database that is triggering the write event.
Is this the default behaviour of the emulator and how do I go about changing or fixing it?
Writes to snapshot.after.ref should go to the database that triggered the Function.
If that is not happening for you, I recommend reporting a bug with a minimal repro on the repo (which should include an entire Cloud Function, and not just the line that you think is going wrong.

Run firebase functions emulator on database without database emulator (towards production cloud instead)

I am having trouble running the firebase functions emulator towards a production database. I have a project which is not publicly released yet so I can run towards production with any negative effects.
My project uses only the realtime database, it does not use Firestore (so other questions on SO are not relevant) The documentation states "Cloud Firestore and Realtime Database triggers already have sufficient credentials, and do not require additional setup." so according to that, I shouldn't need any additional setup in order to point to the production database.
According to all of the documentation on Firebase, the project should run towards the real firebase database if I only start the functions emulator and do not start the database emulator. This warning seems to say so, too:
functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, firestore, database, hosting, pubsub
However, this is not what happens. Instead, I get the following error:
functions[onGlobalClientRequest]: function ignored because the database emulator does not exist or is not running.
I have read the firebase documentation and nothing is really mentioned other than setting credentials should not be needed (but I am setting credentials anyway using export GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json" before running the functions emulator.)
onGlobalClientRequest looks like this:
export const onGlobalClientRequest = functions.database
.ref( client_requests_key + "/{pushedid}")
.onCreate(
async (
snap: functions.database.DataSnapshot,
context: functions.EventContext,
) => {
///.... code here...
},
);
The locally emulated Firebase Functions will be able to write to the Prod database, but will not be able to get triggered by the production database.
Here is a SO answer from a Google employee that states the aforementioned.
Also, quoting from this other SO answer from another Google employee:
In general the rule with emulators:start is that we comprehensively emulate whatever is running. So for example if you're running the Functions and Database emulator, all writes from functions (through admin.database().... will be redirected to the Database emulator. But writes to Firestore (admin.firestore()...) will try and hit production because that emulator is not running.
Operations on a Realtime Database (RTDB) trigger the functions in the corresponding project. So the production RTDB triggers functions of your production project, and the emulated RTDB triggers emulated functions.
If you want to test functions triggered by RTDB operations locally with the emulator, you have to use the RTDB emulator as well. This is explained in the doc here.
If you only want to test HTTP callable functions, then you can use a remote RTDB.

Firebase Cloud Firebase: How to move data between projects in Native mode

I managed to move data between projects using the instructions as per this guide: Moving data between projects.
During the import, I got an error:
ERROR: (gcloud.firestore.import) PERMISSION_DENIED: The Cloud Firestore API has not been used in project XXX before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/firestore.googleapis.com/overview?project=project-name and then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
I enabled Cloud Firestore API and completed the import process.
Now, on Firebase console, when I go the Cloud Firestore page of the destination project, I see this message:
This project is set up to use Cloud Firestore in Datastore mode. This mode can only be accessed from Google Cloud Platform
The import command creates the Cloud Firestore database in Datastore mode. And it's not possible to switch it back Native mode as the first write on the database executed.
How can I import the data in Cloud Firestore Native mode?
I understand the import operation coerced the type of the new project database to Firestore in Datastore mode instead of Firestore Native, which was the mode of the database you exported the data from.
I have opened the following issue tracker so that this behavior could be investigated in further detail. I would recommend to star the issue and add your mail in the CC list so that you're aware of the updates made therein.
Separately, once the first write has been commited to the database it's no longer possible to change the database mode, therefore you'll have to create another project to use Firestore in Native mode.
To that effect I have tested the following workaround so that you could succesfully make the import in a new project:
Create a new project. Then go to the Firebase Console and create a Firestore database.
Using the console, create a mock collection and a mock document within it.
Proceed with the import as outlined in the documentation.
After completing these steps you could delete the mock collection and keep with your development as usual.

Is it possible to test Firestore in Flask Web App locally (without deploying the website)

I am working on small project where data is uploaded to Firestore on one page, and retrieved on another in the same website. Is it possible to test the Firestore integration when the website is hosted on localhost?
When I try accessing the Firestore functionality after deploying my website on localhost, I get:
"google.api_core.exceptions.FailedPrecondition: 400 The Cloud Firestore API is not available for Datastore Mode projects." error.
The only documentation I can find is: "How to deploy Flask Crud API with Firestore..."
Note:
1. I looked at the error, and double checked that my project is in Firestore mode (I created the project from Firebase Console), and then used following in my Flask application to authenticate database:
import firebase_admin
from firebase_admin import credentials
cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)
Any other inputs on this would be appreciated!
I tried looking into Simulators, but most of the documentation said that it's only for Cloud functions, whereas I'm trying to test simple operations.
Thank you for looking into this.
The error message means that your Cloud Firestore database is in Datastore mode instead of Native mode. Unless you never saved anything to your database, you can't change the mode.
Try creating a new project, creating a new Cloud Firestore database, and selecting Native mode:
In the GCP console, it'll ask you to choose.
In the Firebase console, it'll automatically select Native mode.
I found out the issue. I was using cred = credentials.Certificate("path/to/serviceAccountKey.json") code with new generated private key for authenticating my firestore database, however, system was taking an old $GOOGLE_APPLICATIONS_CREDENTIALS for this purpose.
Updating that to new key fixed the issue, and yes, I am able to test FLASK app integration with Firestore on Localhost :)
export GOOGLE_APPLICATION_CREDENTIALS='/Users/..../newkey.json'

maintain connection status of user with firestore. using firebase db and cloud function

I am trying to maintain connection status of user with firestore . but i don't understand some points.
Link : https://firebase.google.com/docs/firestore/solutions/presence
i refer the above link description but i don't understand how to write code.
see the below given topics:
Using presence in Realtime Database
where to write this given code in application or Cloud functions?
2.Connecting to Cloud Firestore
Updating Cloud Firestore's local cache
where to write local cache update code?
I use this in my android application.
Each section of the code in the Build Presence in Cloud Firestore is marked.
If it is marked with WEB, you'll need to run this code in your web application. If your clients are native Android or iOS, you'll need to write and run similar code for those platforms.
If the code is marked with NODE.JS, you will need to run this code in a Node.js environment. It should be possible to accomplish the same in Cloud Functions, but no sample is provided for that.

Resources