Firestore offline batch delete - firebase

I am new to firebase and firestore and would like to know if the behavior I found is a bug or by design.
I am using angularfire2 in my ionic project where the user will be offline most of the timeā€¦ so offline support is a big deal.
The problem: snapshotChanges is not called in a offline batch delete of subcolletion.
I have something like this in firestore /users/{userId}/projects/{projectId}/points/{pointId}
When a user inserts a new project or point a use set and the object is written fine, my lists are updated with the new instance and it works great thanks to snapshotChanges. When the user removes a project is the problem..
I execute a batch delete in the points of a project and after that I delete the project itself. This works fine online, but not offline. My lists are not being updated even though the operation completes with success. I could reproduce it multiple times, but only if the app is offline all the time ( the inserts and deletes are only local)
am I missing something?
The documentation states here:
Batched writes have fewer failure cases than transactions and use
simpler code. They are not affected by contention issues, because they
don't depend on consistently reading any documents. Batched writes
execute even when the user's device is offline.
This "Batched writes execute even when the user's device is offline" this makes me understand that the events of removal should be propagated to snapshotChanges.

Related

How to use firebase realtime-database in offline mode in Flutter app?

I came across a wonderful feature of Firebase offline feature. I integrated that in my app just by writing one line of code in my main.dart file after initializing Firebase await FirebaseDatabase.instance.setPersistenceEnabled(true);
Question 1 :
I couldn't able to understand the database.keepSynced(true) function because without using this line of code, my app is persisting old as well as fetching new updated data, so what this exactly does ?
Question 2 :
How could I prevent the write operations when a user is offline, because I read that after setting persistence enabled, it makes a queues of write operations and update them when user gets online, so how could I stop this ?
Question 3 :
Is this persistence feature going to work in IOS device as well or need some permission settings first ?
Thanks
When you call FirebaseDatabase.instance.setPersistenceEnabled(true) you're allowing Firebase to create a local file on the device where it persists any data it's recently read, and all writes that are pending while the device is offline.
When you call keepSynced(true) on a node, you are telling the SDK to always keep that node synchronized. It essentially creates a onValue listener on the node without any handler code, so you're purely doing this to keep the data synchronized for when the device does go offline.
By combining keepSynced(true) with setPersistenceEnabled(true), you're specifying that you want the app to continue working when it's offline across restarts, and which data is needed for that.
If you call keepSynced(true) on the root of your database, you're telling the SDK to synchronize all data in the database to the disk cache. While this may initially be a quick way to get offline mode for your app working, it typically won't scale when you more people start using your app.
If you only want to allow write operations while the client has a connection to the database backend, you can register a local listener to the .info/connected node, which is a true value when there is a connection and false otherwise.
Note that Firebase doesn't require this, as it queues the pending writes and executes them when the connection is restored. In general, I'd recommend working with the system here instead of against it, and also trying to make your app work gracefully in the offline scenario. In many cases there is no need to disable functionality while the app is offline.
Offline disk persistence is available on Android and iOS, but not on web.

What exactly does Firestore synchronization do?

https://firebase.google.com/docs/firestore says:
Like Realtime Database, Cloud Firestore uses data synchronization to update data on any connected device.
I'm trying to figure out what this "data synchronization" consists of.
https://firebase.google.com/docs/firestore/manage-data/enable-offline says:
When persistence is enabled, Cloud Firestore caches every document received from the backend for offline access.
Does Cloud Firestore update that cache whenever changes happen in the back end?
For example, if I have a certain document in my cache, does the document
update (a) automatically when that document is changed in the back end or
(b) whenever I do a query that uses that document, and I happen to be online
at the time?
UPDATE
I'm going to restate my last paragraph, because it's been misunderstood by
at least one person.
Imagine the following scenario:
I have a smartphone. To make things easy, assume the smartphone
is online all the time.
Installed on this smartphone is a mobile app that contains the Firestore SDK.
The app has enabled the Firestore cache.
The cache contains, say, 1000 documents.
Now my question is: if one of these documents changes in the cloud (not on
the smartphone), under what circumstances will the Firestore SDK update the
document in the cache? Will it (a) update the document automatically, soon
after the change on the cloud, or (b) update the document the next time the
mobile app does a query that uses the document?
Both of the highlighted paragraphs are in my opinion straightforward explanations, and to answer your questions:
Does Firestore update that cache whenever changes happen in the back end?
Yes, if you are offline and some documents are changed, once you are back online, you get all changed documents and vice versa, if you change some documents locally (in your cache), when you're back online, all changed documents are sent to the Firebase servers.
If you have a query that returns 10 documents, it means that you are in sync with 10 documents, which basically means that if of those 10 documents is changed, your listener is triggered only for that change.
does the document update (a) automatically when that document is changed in the back end
Yes, first of all in your cache and once you are back online, also on Firebase servers.
whenever I do a query that uses that document, and I happen to be online at the time?
Whenever you are online and a document is changed, you are notified in realtime.
Edit:
if one of these documents changes in the cloud (not on the smartphone), under what circumstances will the Firestore SDK update the document in the cache? Will it (a) update the document automatically, soon after the change on the cloud, or (b) update the document the next time the mobile app does a query that uses the document?
As long as you are in sync with those documents, it happens in the second moment the document is changed. What I mean through in sync is, that you are using in your code a get() call to get those documents or if you are listening in realtime for documents changes. Simply creating a reference to a document or a query without using a listener, you aren't notified in any way.
update the document the next time the mobile app does a query that uses the document?
Is not correct since you are online and in sync with the documents, the listener is triggered instantly.
Edit2:
In short, a listener is called everytime a change in a document occurs. "Next time the app does the query" is not correct sentence because when you create a query and attach a listener, you are always in sync with the database and when a document is changed you are immediately notified. It is not like, the documents are chainging in the database and when I query (at some point of time), I get the changes, no, you are always notified as the changes occur. That's the beauty of a realtime database, to be notified as the changes are happening :)
If you have the local cache enabled, Firestore automatically stores any documents it receives in that local cache.
This only happens when your app is requesting the documents by calling get() or onSnapshot. Firestore does not automatically request the documents on your behalf. So if your app doesn't request the document, the cache will not be updates.

Where should the code reside to update Firestore?

If I have a Firestore database that I want to constantly be updating (and listeners in my code to constantly be responding to backend updates), should the code that's responsible for updating the database belong in the android app that will be available for download to other people? Or is it supposed to be somewhere else?
For example, the code for creating a document with user info within the collection "Users" belongs in every instance of the app that I publish, because I want every user using my app to be able to write their login info to the Firestore database after they register through Firebase Auth.
But if I have a different collection of data that I want to be available to all users using my app, and I want to be updating that data constantly, should I be updating it with code that goes in with my production level app, or should that be happening somewhere else? And if it should be happening somewhere else, where should that be/how should that be done?
I'd appreciate any help with this!
Never mind, I found the answer to my own question. Firebase provides users with Cloud Functions, which can run on the server-side to respond to new data events.
You might also be interested in Realtime Database, it will mean you don't have to write any of these listeners to the data and it does it all automatically. Check it out here;
https://firebase.google.com/docs/database/rtdb-vs-firestore

How to figure out if firestore security rule failed when client comes back online and pending write completes?

In my Android app I am writing data to firestore which is being validated with the help of security rules. Since writes work offline too, my (invalid) write task will return success if device is offline. But when the device comes online, the security rule will block the write and the data will disappear from the client. Is there a way for me to know that the write failed? Is it possible for a cloud function to be triggered if security rule fails so that I can inform the user that their write failed after going back online?
When you say "my (invalid) write task will return success if device is offline", this is not exactly how it works. When you write a document to Firestore the SDK will only confirm the write if the app is online and the server confirms that it's written. When you perform a write, the API is going to give you some sort of handle into that operation (Android Task, JavaScript promise) will be completed or resolved when that write actually finishes.
If you are offline, you'll never know for sure if the write was going to work, but the written document will still show up in queries. If you want to know if that document finally finished its write, you'll have to request metadata for that document, and check if that document has an outstanding pending write. For example, on Android, use hasPendingWrites() to find out if the document you have in hand was written.
The SDK doesn't provide you with a way of knowing when your documents sync after it's cold booted. But you can take matters into your own hands by remembering all the paths of the documents that are important to track, persist them locally, then load those paths on cold boot to check for success. You'd add listeners to those documents and check:
If the document doesn't exist, that means the write was rejected before you attached the listener.
If the document exists and hasPendingWrites(), that means the sync is still waiting to happen.
If the document exists without pending writes, it got synchronized successfully.
This strategy only works for adding new documents. For updating documents it's more difficult because a document without pending write may just be an old version of the document before the update sync failed. So you'd need to put some other field in the update that indicates if the update succeeded.

Control when Firebase Database syncs data

I'm thinking moving an Android app's persistent data to Firebase Database. Currently I use Sqlite with a Python HTTP REST service.
In the app, I have a big list of cities, called citiesList. Since the list is quite big and hardly updated, I don't want the app fetch the list whenever it goes online.
My current strategy is provide a citiesListVersion. When the app goes online, it checks citiesListVersion. If the server's citiesListVersion is newer, the app will fetch citiesList from server. Otherwise, the app continues working with the cached data.
My question is: can I keep my current strategy when moving to Firebase Database? As I understand, Firebase tries to sync data whenever the app goes online.

Resources