Latency for SQLite update propagation across iCloud - sqlite

I've build a library-style SQLite iOS app using the code in the Recipes sample app, and it works - updates on one device are (eventually) reliably propagated to all other devices running the same app. I've been testing it with multiple events per hour all day long, and all the log transactions do get to every device. However, the time for the updates to propagate is highly variable. If I bring the app up and let it sit, it could be a relatively long time before the cloud sends update transactions to the app, and so what's on-screen remains old data for that same long time. Worse, there's no indication the data is out of date.
If I cause the app to post a change to the cloud, though, updates from the cloud propagate down relatively soon. That suggests that I could put in a hack that periodically posts pointless changes to the database, but even then I won't know if I've received all the changes.
First question: Do methods that will force transactions to propagate exist? a This thread suggests not.
Second question: Is there a way to detect if the local database is out of date? I don't want to tickle the cloud copy incessantly, but doing so now and then until the database is current might not be such a bad idea.

1) if you find such methods, please let me know.
2) same stuff here. I didn't even find any reliable way to detect whether the currently running instance of the iCloud app is not the first instance i.e. other instances have already sent updates to the iCloud until the first push received (which can take some unknown time)

Related

Does Firestore saves the data to the server immediately using `setDoc` using web JS SDK?

I'm trying to analyze some latency issues, and for than want to understand how setDoc works better.
I ran setDoc from one user using the app and it took some time until the other user saw these changes.
It would be expected to see close to immediate reflection of changes by the other user.
My understanding is that setDoc will update the local store immediately, and will also sent a request to the Firestore backend immediately.
However it may take some time until these changes are applied on the server (e.g. if it requires to update indices), and until they are reflected to other users.
Is this correct?
If this is not correct, and Firestore does not send the updates to the server immediately, when does it send the update? Is there a way to flush them immediately?
Introductory note: "Immediately" is somehow difficult to precisely define in the world of asynchronous operations.
My understanding is that setDoc will update the local store
immediately, and will also sent a request to the Firestore backend
immediately. However it may take some time until these changes are
applied on the server (e.g. if it requires to update indices), and
until they are reflected to other users.
If your client device is connected to the internet (i.e. is online), your above statement is correct.
If your client device isn't online the behaviour is different and is explained in the "Access data offline" section of the Firebase documentation.

Can I adjust the Firestore Listener Frequency?

I have a Flutter & Firebase app that provides users with price updates on the dashboard on the main screen. It does this with a Firestore Snapshot Listener, but my read count is flying through the roof (I'm at 203 reads and just 1 device is connected)... This info will only change once a month, and it really doesn't need to keep checking for updates at all times.
Is there a way to setup the listener so that it checks less frequently for updates? Or perhaps, can I setup a Firebase In-App Messaging system with which I send the price out and the app just saves and displays it?
Or is there any efficient solutions?
Since the Listener (which you do not show, so we can't even help you there) ONLY triggers when there is an update to the documents (NOT on a schedule) something is updating the collection you are listening to. 203 is not particularly high over a few days - how long has your app been running? Have you been restarting the app frequently? Most Listeners will give you a result at least once when you initialize them - i.e. when you start the app. There is no "long-term global memory" like that.
A listener will always receive updates as soon as they becomes available. This can't be configured. If you want a different update frequency, you should instead schedule that yourself within the app, and use get() to poll the database as often as you need. You can also use FCM on your backend to push updates to the app, if that works for your case.

Offline Usage. Flutter Hamilton App Architecture. Write to Node and Expect Cloud Function to Update Database and then listener to update UI

The following quote is taken from Google Developer Blog. https://developers.googleblog.com/2017/08/hamilton-app-takes-stage.html
For example, when someone enters the lottery, the app first writes
data to specific nodes in Realtime Database and the database's
security rules help to ensure that the data is valid. The write
triggers a Cloud Function, which runs business logic and stores its
result to a new node in the Realtime Database. The newly written
result data is then pushed automatically to the app.
I understand that instead of making a request and expecting a request, they followed the following pattern:
Write to real-time database
The write trigger an action
The action triggers some logic and function
The function writes data back to the database
The listener on the app gets a notification about the data written on 4.
App updates UI or takes whatever action.
Hamilton app followed this pattern when someone enters the competition for a ticket. My main concern with the pattern is that if the connection is offline, we won't get results and at the same time we won't get an error. The changes will be updated locally and firebase will update the next time there is a connection, which will make things messy, as the user is expecting a result.
I was wondering if there is an easy way or a pattern to follow, so we will get an error and display it.
The first solution that comes to my mind is to somehow add a time on the save operation. If the save is not done on the live database within x seconds then we display an error. At the same time, we will also need a timeout on the reply. So if we do not get a reply within x seconds we display something to the user.
I hope I am not confused as I did not understand the pattern well. I struggled with the title, so if anyone can improve it, please be my guest.
Even building an offline capable app, if an operations chain relies on a Cloud Function, I'd make it impossible to execute while offline, telling user to retry when he's online.
However this might lead to bad situations as well because you need to check connection every time the user tries to execute the ops, which might be painful.

Firestore offline data: Merging writes, maximum time of offline persistence

https://firebase.google.com/docs/firestore/manage-data/enable-offline
How does Firestore work with offline data?
How are writes merged by many clients editing the same data offline, that then come online at the same time?
How long is offline data persisted? If my user uses my app for 5 years offline, then comes back online, will this be an issue? Do offline changes persist after device restarts?
Does query performance of offline data degrade as the data set gets larger?
Im specifically interested in the web Firestore client.
Do all the language clients implement the above in the same manner?
Thanks.
How are writes merged by many clients editing the same data offline, that then come online at the same time?
The write operations that will take place on Firebase servers, will be in the order in which that series of operations happened. The last operation (the most recent one) will be the one that will be available in the database by the time the synchronization occurs.
How long is offline data persisted? If my user uses my app for 5 years offline, then comes back online, will this be an issue?
The problem is not about how long is about how many operations do you make while the device is offline. While offline, Firestore will keep in queue all the write operations. As this queue grows, local operations and app startup will slow down. Nothing major, but over time these may add up. The major problem in this case is that the end result of this will be that the data on the server stays unmodified. Then what is the purpose of a realtime database? Firestore is really designed as an online database that came work for short to intermediate periods of being disconnected, not to stay offline for 5 years. Beside that, in 5 years it might be a problem of compatibility and not of the number of writes.
Do offline changes persist after device restarts?
The offline persistence is also called disk persistence. This type of persistence is enabled by default in Cloud Firestore and it means that recently listened data (as well as any pending writes from the app to the database) are persisted to disk. The data in this cache survives app restarts and device reboots.
Does query performance of offline data degrade as the data set gets larger?
Yes it does, like explained above.
Do all the language clients implement the above in the same manner?
No. For iOS and Android, the offline feature works fine while for web, this feature is still experimental.

How does Firebase deals with events performed while offline?

From Firebase's FAQ:
What happens to my app if I lose my network connection?
Firebase transparently reconnects to the Firebase servers as soon as
you regain connectivity. In the meantime, all Firebase operations done
locally by your app will immediately fire events (...). Once
connectivity is reestablished, you’ll receive the appropriate set of
events so that your client “catches up” with the current server state
Then what happens if I go offline and keep modifying my local data, then come back online and other clients have performed different changes? Which one will ultimately be saved?
If the data on the server gets overridden, does it mean older data can replace newer one?
If the newer data added online is kept, do I know that the data submitted while offline has been discarded?
When your client comes back online, after an offline period and writing data, the behavior of those changes will be determined by which method you used to write them:
The set(), setWithPriority(), remove(), and push() methods are last-write-wins. This means that if offline client A makes a change at t=0, and online client B makes a change at t=10, that offline client A's changes will overwrite client B's changes when upon reconnection. Note that this specifically applies to the changes that were made (i.e. set /a/b/c to 1), not the entire Firebase.
The transaction() method, however, is built specifically for handling conflicts. When offline client A reconnects, your transaction update function will re-run and apply the new change to your Firebase data.
In most applications, users are appending data to lists or modifying individual user state, but not modifying the same piece of data. In the event that multiple users are modifying the same piece of data, you'll want to use transaction() whether you're offline or not.
Generally speaking, Firebase has been built to handle going offline and online automatically and so you shouldn't have to write application code to detect and handle that case.

Resources