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/react-native/sync-data/handle-sync-errors/ below:

Handle Sync Errors - React Native SDK - Atlas Device SDKs

When you use Atlas Device Sync in your Realm app, you can encounter a new class of errors: sync errors.

The Realm React Native SDK can help you detect and handle sync errors. For example, you can write your own sync error handler to respond to specific errors. You can also define how your client app handles client resets.

You should set an error handler for apps that use Atlas Device Sync. A generic error handler will detect and respond to failed sync-related API calls.

A generic sync error handler is a good way to keep track of sync errors. Using FlexibleSyncConfiguration, you can define your error handling behavior.

To add a generic sync error handler:

  1. Write an error handler function.

  2. Create a FlexibleSyncConfiguration object for your RealmProvider.

  3. Pass your error handler to the onError property of the FlexibleSyncConfiguration object.

const syncConfigWithErrorHandling = {  flexible: true,  onError: (_session, error) => {    console.log(error);  },};function RealmWithErrorHandling() {  return (    <RealmProvider sync={syncConfigWithErrorHandling}> <RestOfApp /> </RealmProvider>  );}
Tip

For a list of common Device Sync errors and how to handle them, refer to Sync Errors in the App Services Device Sync documentation.

You may want your sync error handler to specifically address compensating write errors in a way that makes sense for your app. The CompensatingWriteError class can help you identify and react to compensating write errors in your custom error handler.

To handle compensating write errors:

  1. Write an error handler function that uses CompensatingWriteError to identify compensating write errors.

  2. Create a FlexibleSyncConfiguration object for your RealmProvider.

  3. Pass your error handler to the onError property of the FlexibleSyncConfiguration object.

export const CompensatingWriteErrorHandling = () => {  const [error, setError] = useState<CompensatingWriteError | undefined>(    undefined,  );    const errorCallback: ErrorCallback = (_session, error) => {    if (error instanceof CompensatingWriteError) {            console.debug({        code: error.code,        name: error.name,        category: error.category,        message: error.message,        url: error.logUrl,        writes: error.writes,      });      setError(error);    }  };  return (    <AppProvider id={APP_ID}> <UserProvider fallback={LogIn}> <RealmProvider schema={[Person, Turtle]} sync={{ flexible: true, onError: errorCallback, }}> <CompensatingWriteErrorHandler error={error} /> </RealmProvider> </UserProvider> </AppProvider>  );};

A client reset error is a type of sync error where a client realm cannot sync data with the Atlas App Services backend. Clients in this state may continue to run and save data locally but cannot send or receive sync changesets until they perform a client reset.

To learn about the causes of and modes for handling client resets, refer to Device Sync Client Resets in the App Services documentation.

You can specify which client reset mode your app should use to restore the realm to a syncable state:

The Realm SDKs provide client reset modes that automatically handle most client reset errors.

Automatic client reset modes restore your local realm file to a syncable state without closing the realm or missing notifications. The following client reset modes support automatic client resets:

The differences between these modes are based on how they handle changes on the device that have not yet synced to the backend. Only manual recovery mode does not perform an automatic client reset.

Choose recover unsynced changes mode to handle most client reset scenarios automatically. This attempts to recover unsynced changes when a client reset occurs.

If your app requires specific client reset logic that can't be handled automatically, you may want or need to add a manual client reset handler to the automatic client reset mode.

New in version realm@10.23.0.

Client Recovery is a feature that is enabled by default when you configure Device Sync. When Client Recovery is enabled, Realm automatically manages the client reset process in most cases. The client can recover unsynced changes when there are no schema changes, or non-breaking schema changes.

To use Client Recovery, configure your realm with one of the following client reset modes:

When Client Recovery is enabled, these rules determine how objects are integrated, including how conflicts are resolved when both the backend and the client make changes to the same object:

For more information about configuring Client Recovery, refer to Client Recovery in the App Services documentation.

Client Recovery cannot succeed when your app makes breaking schema changes. A breaking change is a change that you can make in your server-side schema that requires additional action to handle. In this scenario, client reset falls back to a manual error client reset fallback.

For information on breaking vs. non-breaking schema changes, refer to Breaking vs. Non-Breaking Change Quick Reference in the App Services documentation.

When you choose recover unsynced changes mode, the client attempts to recover unsynced changes with Client Recovery. Choose this mode when you do not want to fall through to discard unsynced changes.

To handle client resets with the recover unsynced changes mode, pass a ClientResetConfiguration to the clientReset field of your FlexibleSyncConfiguration. Include these properties in the ClientResetConfiguration:

The following example implements recover unsynced changes mode:

const syncConfigWithRecoverClientReset = {  flexible: true,  clientReset: {    mode: 'recoverUnsyncedChanges',    onBefore: realm => {          },    onAfter: (beforeRealm, afterRealm) => {          },    onFallback: (session, path) => {          },  },};function RealmWithRecoverUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithRecoverClientReset}> <RestOfApp /> </RealmProvider>  );}
const syncConfigWithRecoverClientReset = {  flexible: true,  clientReset: {    mode: Realm.ClientResetMode.RecoverUnsyncedChanges,    onBefore: realm => {          },    onAfter: (beforeRealm, afterRealm) => {          },    onFallback: (session, path) => {          },  },};function RealmWithRecoverUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithRecoverClientReset}> <RestOfApp /> </RealmProvider>  );}

In recover or discard unsynced changes mode, the client first attempts to recover changes that have not yet synced. If the client cannot recover unsynced data, it falls through to discard unsynced changes but continues to automatically perform the client reset. Choose this mode when you want to enable automatic client recovery to fall back to discard unsynced changes.

Do not use recover or discard unsynced changes mode if your application cannot lose local data that has not yet synced to the backend.

To handle client resets with the recover or discard unsynced changes mode, pass a ClientResetConfiguration to the clientReset field of your FlexibleSyncConfiguration. Include these properties in the ClientResetConfiguration:

The following example implements recover unsynced changes mode:

const syncConfigWithRecoverDiscardClientReset = {  flexible: true,  clientReset: {    mode: 'recoverOrDiscardUnsyncedChanges',    onBefore: realm => {          },    onAfter: (beforeRealm, afterRealm) => {          },    onFallback: (session, path) => {          },  },};function RealmWithRecoverOrDiscardUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithRecoverDiscardClientReset}> <RestOfApp /> </RealmProvider>  );}
const syncConfigWithRecoverDiscardClientReset = {  flexible: true,  clientReset: {    mode: Realm.ClientResetMode.RecoverOrDiscardUnsyncedChanges,    onBefore: realm => {          },    onAfter: (beforeRealm, afterRealm) => {          },    onFallback: (session, path) => {          },  },};function RealmWithRecoverOrDiscardUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithRecoverDiscardClientReset}> <RestOfApp /> </RealmProvider>  );}

If the client reset with recovery cannot complete automatically, like when there are breaking schema changes, the client reset process falls through to a manual error handler. This may occur in either of the client reset with recovery modes, recover unsynced changes and recover or discard unsynced changes.

You must provide a manual client reset implementation in the SyncConfiguration.onFallback() callback. onFallback() takes two arguments:

The following example demonstrates how you can manually handle this error case by discarding all unsynced changes:

let realm; const syncConfigWithClientResetFallback = {  flexible: true,  clientReset: {    mode: 'recoverOrDiscardUnsyncedChanges',         onFallback: (_session, path) => {      try {                                const didUserConfirmReset = showUserAConfirmationDialog();        if (didUserConfirmReset) {                    realm.close();          Realm.deleteFile(path);                    Realm.App.Sync.initiateClientReset(app, path);                            }      } catch (err) {                      }    },  },};function RealmWithManualClientResetFallback() {  return (    <RealmProvider sync={syncConfigWithClientResetFallback}> <RestOfApp /> </RealmProvider>  );}function RestOfApp() {    realm = useRealm();  return <>{/* Other components in rest of app */}</>;}
let realm; const syncConfigWithClientResetFallback = {  flexible: true,  clientReset: {    mode: Realm.ClientResetMode.RecoverOrDiscardUnsyncedChanges,         onFallback: (_session, path) => {      try {                                const didUserConfirmReset = showUserAConfirmationDialog();        if (didUserConfirmReset) {                    realm.close();          Realm.deleteFile(path);                    Realm.App.Sync.initiateClientReset(app, path);                            }      } catch (err) {                      }    },  },};function RealmWithManualClientResetFallback() {  return (    <RealmProvider sync={syncConfigWithClientResetFallback}> <RestOfApp /> </RealmProvider>  );}function RestOfApp() {    realm = useRealm();  return <>{/* Other components in rest of app */}</>;}

New in version realm@10.11.0.

Changed in version realm@10.23.0: Mode renamed from "discardLocal" to "discardUnsyncedChanges". Both currently work, but in a future version, "discardLocal" will be removed. "clientResetBefore" and "clientResetAfter" callbacks renamed to "onBefore" and "onAfter", respectively.

Discard Unsynced Changes mode permanently deletes all local unsynced changes made since the last successful sync. You might use this mode when your app requires client recovery logic that is not consistent with automatic Client Recovery, or when you don't want to recover unsynced data.

Do not use discard unsynced changes mode if your application cannot lose local data that has not yet synced to the backend.

To handle client resets with the discard unsynced changes mode, pass a ClientResetConfiguration to the clientReset field of your FlexibleSyncConfiguration. Include these properties in the ClientResetConfiguration:

The following example implements discard unsynced changes mode:

const syncConfigWithDiscardClientReset = {  flexible: true,  clientReset: {    mode: 'discardUnsyncedChanges',    onBefore: realm => {      console.log('Beginning client reset for ', realm.path);    },    onAfter: (beforeRealm, afterRealm) => {      console.log('Finished client reset for', beforeRealm.path);      console.log('New realm path', afterRealm.path);    },  },};function RealmWitDiscardUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithDiscardClientReset}> <RestOfApp /> </RealmProvider>  );}
const syncConfigWithDiscardClientReset = {  flexible: true,  clientReset: {    mode: Realm.ClientResetMode.DiscardUnsyncedChanges,    onBefore: realm => {      console.log('Beginning client reset for ', realm.path);    },    onAfter: (beforeRealm, afterRealm) => {      console.log('Finished client reset for', beforeRealm.path);      console.log('New realm path', afterRealm.path);    },  },};function RealmWitDiscardUnsyncedChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithDiscardClientReset}> <RestOfApp /> </RealmProvider>  );}

If your application experiences a breaking schema change, discard unsynced changes mode cannot handle the resulting client reset automatically. Instead, you must provide a manual client reset implementation in the SyncConfiguration error() callback. The following example demonstrates how you can manually handle this error case by discarding all unsynced changes:

async function handleSyncError(session, syncError) {  if (syncError.name == 'ClientReset') {    console.log(syncError);    try {      console.log('error type is ClientReset....');      const path = realm.path;       realm.close();      Realm.App.Sync.initiateClientReset(app, path);                        realm = await Realm.open(config);      realm.close();    } catch (err) {      console.error(err);    }  } else {      }}const syncConfigWithDiscardAfterBreakingSchemaChanges = {  flexible: true,  clientReset: {    mode: 'discardUnsyncedChanges',    onBefore: realm => {            console.log('Beginning client reset for ', realm.path);    },    onAfter: (beforeRealm, afterRealm) => {                  console.log('Finished client reset for', beforeRealm.path);      console.log('New realm path', afterRealm.path);    },  },  onError: handleSyncError, };function RealmWitDiscardAfterBreakingSchemaChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithDiscardAfterBreakingSchemaChanges}> <RestOfApp /> </RealmProvider>  );}
async function handleSyncError(session, syncError) {  if (syncError.name == 'ClientReset') {    console.log(syncError);    try {      console.log('error type is ClientReset....');      const path = realm.path;       realm.close();      Realm.App.Sync.initiateClientReset(app, path);                        realm = await Realm.open(config);      realm.close();    } catch (err) {      console.error(err);    }  } else {      }}const syncConfigWithDiscardAfterBreakingSchemaChanges = {  flexible: true,  clientReset: {    mode: Realm.ClientResetMode.DiscardUnsyncedChanges,    onBefore: realm => {            console.log('Beginning client reset for ', realm.path);    },    onAfter: (beforeRealm, afterRealm) => {                  console.log('Finished client reset for', beforeRealm.path);      console.log('New realm path', afterRealm.path);    },  },  onError: handleSyncError, };function RealmWitDiscardAfterBreakingSchemaChangesClientReset() {  return (    <RealmProvider sync={syncConfigWithDiscardAfterBreakingSchemaChanges}> <RestOfApp /> </RealmProvider>  );}

Changed in version realm@10.23.0: onManual callback added

In manual mode, you define your own client reset handler. You might want to use a manual client reset handler if the Automatic Recovery logic does not work for your app and you can't discard unsynced local data.

To handle client resets with manual mode, pass a ClientResetConfiguration to the clientReset field of your FlexibleSyncConfiguration. Include these properties in the ClientResetConfiguration:

const syncConfigWithManualClientReset = {  flexible: true,  clientReset: {    mode: 'manual',    onManual: (session, path) => {          },  },};function RealmWitManualClientReset() {  return (    <RealmProvider sync={syncConfigWithManualClientReset}> <RestOfApp /> </RealmProvider>  );}
const syncConfigWithManualClientReset = {  flexible: true,  clientReset: {    mode: 'manual',    onManual: (session, path) => {          },  },};function RealmWitManualClientReset() {  return (    <RealmProvider sync={syncConfigWithManualClientReset}> <RestOfApp /> </RealmProvider>  );}

To recover data from a manual client reset requires significant amounts of code, schema concessions, and custom conflict resolution logic. If you need to implement your own custom client reset logic, see the Advanced Guide to Manual Client Reset Data Recovery.

You can manually test your application's client reset handling by terminating and re-enabling Device Sync.

When you terminate and re-enable Sync, clients that have previously connected with Sync are unable to connect until after they perform a client reset. Terminating Sync deletes the metadata from the server that allows the client to synchronize. The client must download a new copy of the realm from the server. The server sends a client reset error to these clients. So, when you terminate Sync, you trigger the client reset condition.

To test client reset handling:

  1. Write data from a client application and wait for it to synchronize.

  2. Terminate and re-enable Device Sync.

  3. Run the client app again. The app should get a client reset error when it tries to connect to the server.

Warning

While you iterate on client reset handling in your client application, you may need to terminate and re-enable Sync repeatedly. Terminating and re-enabling Sync renders all existing clients unable to sync until after completing a client reset. To avoid this in production, test client reset handling in a development environment.


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