Client Resets - .NET SDK
When using Atlas Device Sync, it is possible that your client app will need to handle a client reset. While not a common event, you need to perform a client reset when Sync is terminated on the server. For example, when a developer deploys a change that includes a destructive schema change. To fix this, you must stop Sync, modify the schema, and then re-enable Sync. This process causes the server to send a client reset message to the clients.
By default, the SDK handles client reset messages automatically, but only on app startup. Until the app is restarted, users will receive no new data from the server, and any changes on the device are lost when the app is restarted and the reset happens.
A client reset erases all local data and downloads a new copy of the data stored in MongoDB Atlas. Performing a client reset loses all local changes made since the client last successfully synced.
The .NET SDK provides the option to specify a client
reset strategy in your PartitionSyncConfiguration and
FlexibleSyncConfiguration. The
ClientResetHandler property can be set to either the
DiscardLocalResetHandler method (for PartitionSyncConfiguration
),
or the ManualRecoveryHandler method for either configuration
type. If you do not specify a ClientResetHandler
, the default is
ManualRecoveryHandler
.
Using the DiscardLocalResetHandler
When you specify a DiscardLocalResetHandler
on a
PartitionSyncConfiguration
object, the SDK automatically performs
a client reset with minimal code and minimal disruption to your application
workflow. This client reset mode restores your local realm file to a syncable
state without closing the realm and while maintaining notifications.
Be aware that this strategy permanently deletes all local unsynced changes
made since the last successful sync. For a better user experience, consider using
the OnBeforeReset
and OnAfterReset
callback methods. Within the OnBeforeReset
callback method, notify the user
that a reset is about to happen, and then in the OnAfterReset
callback method,
notify the user when the reset is complete.
If the client reset operation cannot complete when using the
DiscardLocalResetHandler
method -- as in the case of a destructive schema
change -- the client reset process reverts to manual
mode. You specify the method for handling a manual reset with the
ManualResetFallback
callback method.
The following example shows how you might configure the OnBeforeReset
,
OnAfterReset
, and ManualResetFallback
callbacks.
private void SetupRealm() { var config = new PartitionSyncConfiguration("myPartition", user); config.ClientResetHandler = new DiscardLocalResetHandler() { OnBeforeReset = HandleBeforeResetCallback, OnAfterReset = HandleAfterResetCallback, ManualResetFallback = HandleManualResetCallback }; var realm = await Realm.GetInstanceAsync(config); } private void HandleBeforeResetCallback(Realm beforeFrozen) { // Notify the user that a reset is going to happen. // This method may also be useful if you want to make a backup // of the existing Realm before it is reset by the system. } private void HandleAfterResetCallback(Realm beforeFrozen, Realm after) { // Notify the user when the reset is complete. // This method may also be useful if you want to merge in changes // that were in the "before" Realm into the re-created Realm } private void HandleManualResetCallback(ClientResetException clientResetException) { // An error occurred. Use this method to perform a manual client reset. // Prompt user to perform client reset immediately. If they don't do it, // they won't receive any data from the server until they restart the app // and all changes they make will be discarded when the app restarts. var didUserConfirmReset = ShowUserAConfirmationDialog(); if (didUserConfirmReset) { // Close the Realm before doing the reset. It must be // deleted as part of the reset. realm.Dispose(); // perform the client reset var didReset = clientResetException.InitiateClientReset(); if (didReset) { // Navigate the user back to the main page or reopen the // the Realm and reinitialize the current page. } else { // Reset failed - notify user that they'll need to // restart the app. } } }
Using the ManualRecoveryHandler
To handle manual client resets, set the
ClientResetHandler
property of the FlexibleSyncConfiguration
object to a
ManualRecoveryHandler(ClientResetException)
method. Be sure to use the overload of the ManualRecoveryHandler
that takes a
ClientResetException
parameter.
Within the ManualRecoveryHandler
, dispose the existing realm, and then call the
InitiateClientReset()
method.
The following example demonstrates this:
private void SetupRealm() { app = App.Create(myRealmAppId); user = app.LogInAsync( Credentials.EmailPassword("valerie@mongodb.com", "astral")).Result; var config = new FlexibleSyncConfiguration(user); config.ClientResetHandler = new ManualRecoveryHandler(HandleSessionError); var realm = await Realm.GetInstanceAsync(config); } private void HandleSessionError(ClientResetException clientResetException) { Console.WriteLine($"Client Reset requested: {clientResetException.Message}"); // Prompt user to perform a client reset immediately. If they don't do it, // they won't receive any data from the server until they restart the app // and all changes they make will be discarded when the app restarts. var didUserConfirmReset = ShowUserAConfirmationDialog(); if (didUserConfirmReset) { // Close the Realm before doing the reset. It must be // deleted as part of the reset. fsRealm.Dispose(); // perform the client reset var didReset = clientResetException.InitiateClientReset(); if (didReset) { // Navigate the user back to the main page or reopen the // the Realm and reinitialize the current page. } else { // Reset failed - notify user that they'll need to // restart the app. } } }