I am using firebase as a database for a mobile application. Mobile application version 1 using a certain DB structure. But in version 2 I have a major schema changes. I could not find any specific documentation which would mention the best practices for managing DB upgrades. So I am thinking of following steps, which looks good on paper.
Application version 1 is in production using firebase/v1
Copy version 1 schema firebase/v1 to firebase/v2
Upgrade firebase/v2 schema
Disable write operations on firebase/v1
Distribute application v2 pointing to firebase/v2
With these steps users with older versions app would be able to only read the data. So unless they dont upgrade the app they wont be able to modify any data.
Do I going in the right direction in managing my schema updates? Or is there any better way to do this.
Use cloud function database functions to migrate data from db/v1 to db/v2. On update event in db/v1, you can write to db/v2 in parallel, so all active user data can move into db/v2.
https://firebase.google.com/docs/functions/database-events
Migrate data asap!
Related
As I plan for how to structure my data in Firestore to optimize for my use-case, I can't help but wonder what would happen if in the future I need to update the path of my data in Firestore?
Will I need to implement some mechanism of notifying all older versions of my mobile app to stop starting and require upgrades? Or a safety check when the app starts that reads a location in Firestore to decide whether the client needs to upgrade or can continue using the current version?
It seems like paths to data are supposed to be hardcoded in the client code, which can pose risk, especially for improvements in the product when data structure in Firestore is complicated (subcollections, etc)
Is there a way to better plan for this kind of a disaster in Firestore?
The first goal should be to make any database changes backwards compatible. It's possible a lot more often than you may think now.
But if you really want to prepare for incompatible changes you should include a version number in your database. In Cloud Firestore you'd typically put that in a global collection in a known document name, such as /Globals/VersionNumber. Note that this is the version number of the data model, not necessarily the version number of the app.
Now when the app starts, it reads that document first and checks if the version number matches with what it was made for. If it doesn't, tell the user to upgrade. Otherwise continue as usual.
Firestore a NOSQL is a Document oriented database. Now how to manage versioning of the data as I use it with Firebase SDK and Android applications?
For e.g. let's say I have a JSON schema that I launch with my 1.0.0version of my android app. Later 1.0.1 comes up where I have to add some extra fields for the newer documents. Since I changed the structure to have additional information, it only applies to new documents.
Therefore, using this logic, I can see my Android application must be able to deal with all versions of JSON tree if used against this project I create in the firebase console with Firestore. But this can be very painful right, that I have carry the deadweight of backward compatibility endlessly? Is there a way to have some sort of version like in protobuf or something the android app can send to firestore server side so that automatically we can do something to prevent crashes on the android app when it sees new fields?
See also this thread, the kind of problem the engineer has posted. You can end up with this kind of problem as new fields get discovered in your JSON tree by the android app
Add new field or change the structure on all Firestore documents
Any suggestions for how we should go about this?
In node.js architecture we handle this with default-> v1.1/update or
default-> v1.0/update, that way we can manage the routes.
But for android+firebase SKD-> talking to Firestore NOSQL, how do I manage the versioning of the json schema.
We come up to next versioning with Firestore:
prefer additive changes, backward compatible -> keeping structure
as it was, but with adding new fields (that can be ignored by old
mobile clients)
in case it is impossible, and we are doing backward
incompatible change: we have a collection in Firestore, called 'versioning', where store clients with allowed versions. Then mobile application on lunch fetch this version for current platform and compare version from configuration with stored in Firestore - if version is less then min allowed, force upgrade required, else if version less then current, we recommend updating the client, otherwise all is fine.
I have developed an Android APP based on Firestore for DB storing data.
Now I need that the user is able to configure on the APP at run-time the end-point of Firestore DB - these parameters are typically stored in google-services.json (firebase_url, project_id, storage_bucket)
How can these values be changed at run time? Is there a specific Android API to do this?
Thanks in advance for any suggestion/support on this matter :)
You will have to take control of the initialization of your app, rather than allow the default initialization. This is kind of complicated, and it involves calling FirebaseApp.initializeApp() correctly with the details of the project you're trying to access.
I've written a couple blogs about this:
https://firebase.googleblog.com/2016/12/how-does-firebase-initialize-on-android.html
https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html
I am trying to implement a service to backup the SQLite database of my Android app. I am planning to both schedule this service for frequent backups (every day for example), and add an option to launch it immediately.
My problem is that the service might start while the application is running, or the user might start the application while the backup is in progress. And they may write to the database while I am copying it.
Is there any way to make sure that the copy and write will not run concurrently, without adding synchronization locks to all my queries ?
Thanks !
If you are not using explicit transactions, SQLite will automatically use a transaction around each SQL statement.
To ensure that the database files cannot be accessed by another database connection while you are doing the backup, open an exclusive transaction around the backup.
SQLite site has some notes on doing hot backup on a running database. See the Example 2 in that page.
In android, if you want to initiate a file copy of your sqlite db file, you will first need to get a shared lock as mentioned above, but this approach has shortcomings.
Ideally, you would want to use the sqlite3_backup_* apis.
These APIs are not available in standard android sqlite API, but it is easy to copy the sqlite jni code to your project, and expose these additional features. The advantage with this approach is that you dont have to change existing API calls in your code, as it mirrors existing android sqlite API definitions.
To expose backup APIs, take a look at android_database_SQLiteConnection.cpp to see how existing JNI functions call the native sqlite_* APIs.
Another option is to use something like sqlite4java, it has the sqlite backup APIs wrapped in as Java APIs, and seems the latest version supports Android.
I realize that Google App Engine (GAE) is very powerful and I would like to determine the proper way to create the database schema (outside of Android) and start populating the database (once my Android app is deployed). Then I would like to query the database (outside of Android). I was hoping that this would be a 10-20 line exercise but it is turning into a much harder task that I anticipated.
Out of Band Steps
Create Database via command line using proper GAE authorization.
Query Database via command line using proper GAE authorization.
I want to reiterate that I don't want to write Java code to create or query the database. I am more interested in using SQL or a SQL-like language directly vs. using Java.
Android Steps
Insert rows into the database using proper GAE authorization, encryption, etc.
Here are two ways to issue SQL statements to your Cloud SQL instance:
https://developers.google.com/cloud-sql/docs/commandline
https://developers.google.com/cloud-sql/docs/sql_prompt
As for inserting rows into the database from Android, you'll need to write a GAE app to act as a proxy. The app can then expose a REST API or whatever API you want.
I realise this is an old post but for people finding this via search, the link below is relevant and includes a sample android code:
https://developers.google.com/appengine/docs/java/endpoints/consume_android
Also, the Google Eclipse pluging also supports creating an App Engine Android project, see:
https://developers.google.com/eclipse/docs/endpoints-androidconnected-gae