How to track progress in MongoDB Realm on initial sync?

I’m planning to develop a Windows application with an offline-first approach. I found MongoDB Realm with the .Net SDK that seems to suit my requirements. Currently I’m trying to find out how I can track the upload/download progress when connecting to the server database (especially for the first time).

I connect like this:

config = new SyncConfiguration("myPart", user); 
var realm = await Realm.GetInstanceAsync(config);

Then I found this snippet in the Realm documentation to track for example the download-progress:

var token = session.GetProgressObservable(ProgressDirection.Download, ProgressMode.ReportIndefinitely)
                   .Subscribe(progress =>
                   {
                       if (progress.TransferredBytes < progress.TransferableBytes)
                       {
                           // Show progress indicator
                       }
                       else
                       {
                           // Hide the progress indicator
                       }
                   });

The problem for me is, that I need to have a session-handle to subscribe to the progress event. But I can get the session only after I opened the realm (with realm.GetSession() ). And as I open the realm async I will not get the realm before Realm.GetInstanceAsync(config) is completed, which makes the progress-tracker useless.

What can I do to get the progress during the sync? Thank you

1 Like

When you open the realm asynchronously (i.e. with GetInstanceAsync) the async call doesn’t resolve until the SDK has synced all pending sync changes. Try opening the realm synchronously (i.e. with GetInstance) - it should return the realm immediately and then start syncing changes in the background, which you can observe using the code you posted.

Hope that helps!

Except that your sync documentation says:

The first time a user logs on to your realm app, you should open the realm asynchronously to sync data from the server to the device.

I replied to the same question in StackOverflow. The gist of it is:

config = new SyncConfiguration("myPart", user)
{
     OnProgress = progress =>
     {
         Console.WriteLine($"Progress: {progress.TransferredBytes}/{progress. TransferableBytes}");
     }
}
3 Likes

X-POST on SO - https://stackoverflow.com/questions/64929888/how-to-track-progress-in-mongodb-realm-on-initial-sync/64969343#64969343

thanks for the replies and sorry for the crosspost. As nobody was replying in SO I thought I might get some help here. But then @nirinchev replied which helped me already.

With his method I get a progress for GetInstanceAsync(), which I need, because GetInstance()creates and error when you try the initial sync with it. I wanted to go now one setup further and did this:

    SyncConfig = new SyncConfiguration("myPart",User)
    {
        OnProgress = progress =>
        {
            Console.WriteLine($"Progress: {progress.TransferredBytes}/{progress.TransferableBytes}");
        }
    };
    Realm1 = await Realm.GetInstanceAsync(SyncConfig);
    var session = Realm1.GetSession();

    var uploadProgress = session.GetProgressObservable(ProgressDirection.Upload, ProgressMode.ReportIndefinitely);
    var downloadProgress = session.GetProgressObservable(ProgressDirection.Download, ProgressMode.ReportIndefinitely);

    var token = uploadProgress.CombineLatest(downloadProgress, (upload, download) => new
        {
            TotalTransferred = upload.TransferredBytes + download.TransferredBytes,
            TotalTransferable = upload.TransferableBytes + download.TransferableBytes
        })
        .Throttle(TimeSpan.FromSeconds(0.1))
        .ObserveOn(SynchronizationContext.Current)
        .Subscribe(progress =>
        {
            if (progress.TotalTransferred < progress.TotalTransferable)
            {
                // Show spinner
                Console.WriteLine($"ProgressIF: {progress.TotalTransferred}/{progress.TotalTransferable}");
            }
            else
            {
                // Hide spinner
                Console.WriteLine($"ProgressELSE: {progress.TotalTransferred}/{progress.TotalTransferable}");
            }
        });

But this unfortunately creates another error:

Unbehandelte Ausnahme: System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
   bei Realms.Sync.SessionHandle.HandleSessionProgress(IntPtr tokenPtr, UInt64 transferredBytes, UInt64 transferableBytes) in C:\jenkins\workspace\realm_realm-dotnet_PR-2097\Realm\Realm\Handles\SessionHandle.cs:Zeile 220.
Das Programm "[16928] MongoDBDemo.exe" wurde mit Code 0 (0x0) beendet.

And as this error seems to occur in the Realm.dll I can’t debug it to further understand why I get this error.

Hm, this indeed sounds like a bug on our end - I’ll take a look and get back when I have more information.

Looking at the code, it appears that this is a flaw in the design of our ProgressObservable implementation - combining it with another observable will not correctly retain the notification token from both, so it gets garbage collected. I’ll file a bug and we’ll fix it in the next release.

1 Like