A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.mongodb.com/docs/atlas/device-sdks/sdk/node/sync/client-reset-data-recovery/ below:

Manual Client Reset Data Recovery - Node.js SDK - Atlas Device SDKs

This page explains how to manually recover unsynced realm data after a client reset using the Manual Recovery client reset mode.

Manual recovery requires significant amounts of code, schema concessions, and custom conflict resolution logic. You should only perform a manual recovery of unsynced realm data if you cannot lose unsynced data and the other automatic client reset methods do not meet your use case.

For more information about the other available client reset modes, refer to Reset a Client Realm.

The specifics of manual recovery depend heavily upon your application and your schema. However, there are a few techniques that can help with manual recoveries. The Track Changes by Object Strategy section demonstrates one method of recovering unsynced changes during a client reset.

Warning Avoid Making Breaking Schema Changes in Production

Do not expect to recover all unsynced data after a breaking schema change. The best way to preserve user data is to never make a breaking schema change at all.

Important Breaking Schema Changes Require an App Schema Update

After a breaking schema change:

The track changes by object manual client reset data recovery strategy lets you recover data already written to the client realm file but not yet synced to the backend.

In this strategy, you add a "Last Updated Time" to each object model to track when each object last changed. We'll watch the to determine when the realm last uploaded its state to the backend.

When backend invokes a client reset, find objects that were deleted, created, or updated since the last sync with the backend. Then copy that data from the backup realm to the new realm.

The following steps demonstrate implementing the process at a high level:

  1. Client reset error: Your application receives a client reset error code from the backend.

  2. Strategy implementation: The SDK calls your strategy implementation.

  3. Close all instances of the realm: Close all open instances of the realm experiencing the client reset. If your application architecture makes this difficult (for instance, if your app uses many realm instances simultaneously in listeners throughout the application), it may be easier to restart the application. You can do this programmatically or through a direct request to the user in a dialog.

  4. Move the realm to a backup file: Call the Realm.App.Sync.initiateClientReset() static method. This method moves the current copy of the client realm file to a backup file.

  5. Open new instance of the realm: Open a new instance of the realm using your typical sync configuration. If your application uses multiple realms, you can identify the realm experiencing a client reset from the backup file name.

  6. Download all realm data from the backend: Download the entire set of data in the realm before you proceed. This is the default behavior of the SyncConfiguration object.

  7. Open the realm backup: Use the error.config object passed as an argument to the SyncConfiguration.error callback function.

  8. Migrate unsynced changes: Query the backup realm for data to recover. Insert, delete or update data in the new realm accordingly.

This example demonstrates implementing the track changes by object manual client reset data recovery strategy.

Note Limitations of This Example

For more information on other ways to perform a manual client reset with data recovery, refer to the Alternative Strategies section.

Add a new property to your Realm object schema to track the last time it was updated. Whenever you create or update a Realm object with the schema, include a timestamp with the update time.

Ordinarily, there is no way to detect when a Realm object was last modified. This makes it difficult to determine which changes were synced to the backend. By adding a timestamp lastUpdated to your Realm object models and updating that timestamp to the current time whenever a change occurs, you can keep track of when objects were changed.

const DogSchema = {  name: "Dog",  properties: {    name: "string",    age: "int?",    lastUpdated: "int",  },};

In the realm's SyncConfiguration, set the clientReset field to manual mode and include an error callback function. You'll define the error callback function in the Create Callback to Handle Client Reset section.

const config = {  schema: [DogSchema],  sync: {    user: app.currentUser,    partitionValue: "MyPartitionValue",    clientReset: {      mode: "manual",    },    error: handleSyncError,   },};

Just knowing when objects were changed isn't enough to recover data during a client reset. You also need to know when the realm last completed a sync successfully. This example implementation uses a singleton object in a separate realm called LastSynced paired with a change listener to record when a realm finishes syncing successfully.

Define your LastSynced Realm to track the latest time your realm synchronizes.

const LastSyncedSchema = {  name: "LastSynced",  properties: {    realmTracked: "string",    timestamp: "int?",  },  primaryKey: "realmTracked",};const lastSyncedConfig = { schema: [LastSyncedSchema] };const lastSyncedRealm = await Realm.open(lastSyncedConfig);lastSyncedRealm.write(() => {  lastSyncedRealm.create("LastSynced", {    realmTracked: "Dog",  });});

Register a change listener to subscribe to changes to the Dog collection. Only update the LastSynced object if the sync session is connected and all local changes have been synced with the server.

realm.objects("Dog").addListener(async () => {      if (realm.syncSession.isConnected()) {    await realm.syncSession.uploadAllLocalChanges();    lastSyncedRealm.write(() => {      lastSyncedRealm.create("LastSynced", {        realmTracked: "Dog",        timestamp: Date.now(),      });    });  }});

Now that you've recorded update times for all objects in your application as well as the last time your application completed a sync, it's time to implement the manual recovery process. This example handles two main recovery operations:

You can follow along with the implementation of these operations in the code samples below.

async function handleSyncError(_session, error) {  if (error.name === "ClientReset") {    const realmPath = realm.path;     realm.close();         Realm.App.Sync.initiateClientReset(app, realmPath);        realm = await Realm.open(config);    const oldRealm = await Realm.open(error.config);    const lastSyncedTime = lastSyncedRealm.objectForPrimaryKey(      "LastSynced",      "Dog"    ).timestamp;    const unsyncedDogs = oldRealm      .objects("Dog")      .filtered(`lastUpdated > ${lastSyncedTime}`);        realm.write(() => {      unsyncedDogs.forEach((dog) => {        realm.create("Dog", dog, "modified");      });    });        const syncedDogs = realm      .objects("Dog")      .filtered(`lastUpdated <= ${lastSyncedTime}`);    realm.write(() => {      syncedDogs.forEach((dog) => {        if (!oldRealm.objectForPrimaryKey("Dog", dog._id)) {          realm.delete(dog);        }      });    });        await realm.syncSession.uploadAllLocalChanges();    oldRealm.close();  } else {    console.log(`Received error ${error.message}`);  }}

Possible alternate implementations include:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4