@nirinchev Thanks a lot for the detailed reply.
We were playing with these APIs the past few days and I wanted to come up with a complete report before replying to this message, hence, sorry for the bit delayed reply.
First of all WaitForDownloadAsync and WaitForUploadAsync methods were exactly the ones we needed! I didn’t know about their existence and they worked like a charm.
However, there are problems with the GetProgressObservable method. No matter whether we track the upload or the download progress, and whether we use ProgressMode.ForCurrentlyOutstandingWork or ProgressMode.ReportIndefinitely TransferredBytes/TransferableBytes are accumulative. What I mean by that? Let’s take an example of the upload. Here are some real numbers:
- I launch the app and make some changes, after all of the changes are synced here here’s what we get as final upload progress -
[12:53:58 INF] Upload progress: 2121568/2121568 - I close the application and reopen it, make more changes here is the first progress message I get -
[12:55:22 INF] Upload progress: 2121568/2134356
Notice how the TransferredBytes were recovered from the previous session and the TransferableBytes increase with the new changes, which is logical.
The same behavior is present in the download progress. Is this by design? I wouldn’t say so. I would assume, whenever I use ProgressMode.ForCurrentlyOutstandingWork as soon as I am subscribed to this observable, it should tell me how many bytes need to sync as for the current moment, and how many of those were synced, but definitely not how many bytes in general have been synced through the lifetime of the application.
The behaviour that we want to achieve is whenever data is changed in the realm, we will subscribe to the progress observable and monitor the progress of the currently pending changes and show a progress bar in the app. To make sure we don’t do that for every single change, we buffer the changes using the reactive Throttle operator. Here is the reactive chain that we’ve built
//Monitor all realm data changes for the synced realm instance
Observable.FromEventPattern<Realm.RealmChangedEventHandler, EventArgs>(handler => syncedRealm.RealmChanged += handler,
handler => syncedRealm.RealmChanged -= handler)
.Select(_ => syncedRealm)
//Combine changes happened within the past 10 seconds
.Throttle(TimeSpan.FromSeconds(10))
//Get the progress observable
.Select(realm => new SyncProgressObservable(_logger, realm.GetSession().GetProgressObservable(ProgressDirection.Upload, ProgressMode.ReportIndefinitely)))
//Now we have observable of sync observables. By using the Switch operator we dispose the previous subscription after we subscribe to the new one
.Switch();
I think I could add some more reactive operators that essentially would track the delta progress. For instance, as soon as we create a new subscription read the current accumulated progress and subtract so we start from zero every time for the current batch. However, before doing so, I want to confirm with you that the behaviour I see is by design and not a bug. And if it’s by design, I would really like to understand the rationale behind this kind of implementation.