Cuando usas Atlas Device Sync en tu aplicación Realm, puedes encontrar una nueva clase de errores: errores de sincronización
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.
Controlador de errores de sincronización
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ñade un controlador genérico de errores de sincronizar
Un manejador de errores de sincronización genérico es una buena forma de rastrear los errores de sincronización. Al usar FlexibleSyncConfiguration, puedes definir tu comportamiento de gestión de errores.
To add a generic sync error handler:
Escriba una función de manejo de errores.
Crear un(a)
FlexibleSyncConfigurationobjeto para suRealmProvider.Pass your error handler to the
onErrorproperty of theFlexibleSyncConfigurationobject.
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.
Manejar errores de escritura compensatorios
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:
Escriba una función de manejo de errores que utilice
CompensatingWriteErrorpara identificar errores compensatorios de escritura.Cree un objeto
FlexibleSyncConfigurationpara suRealmProvider.Pass your error handler to the
onErrorproperty of theFlexibleSyncConfigurationobject.
export const CompensatingWriteErrorHandling = () => { const [error, setError] = useState<CompensatingWriteError | undefined>( undefined, ); // Create a callback for sync error handling using CompensatingWriteError const errorCallback: ErrorCallback = (_session, error) => { if (error instanceof CompensatingWriteError) { // Handle the compensating write error as needed 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> ); };
Manejar errores de restablecimiento del cliente
Un error de restablecimiento del cliente es un tipo de error de sincronización donde un realm cliente no puede sincronizar datos con el backend de Atlas App Services. Los clientes en este estado pueden seguir ejecutándose y guardando datos localmente pero no podrán enviar o recibir conjuntos de cambios de sincronización hasta que realicen un restablecimiento del cliente.
To learn about the causes of and modes for handling client resets, refer to Device Sync Client Resets in the App Services documentation.
Client Reset Modes
Puede especificar qué modo de restablecimiento de cliente debe utilizar su aplicación para restaurar el realm a un estado sincronizable:
Modo de recuperación de cambios no sincronizados: Al seleccionar este modo, el cliente intenta recuperar los cambios no sincronizados. Elija este modo si no desea descartar los cambios no sincronizados.
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.
Modo descartar cambios no sincronizados: restaura el reino a un estado sincronizable descartando los cambios realizados desde la última sincronización.
Manual recovery mode: Downloads a new copy of the realm, and moves the unsyncable realm to a backup. Migrate unsynced data from the backup copy of the realm to the new syncable copy.
Automatic vs. Manual Client Reset
The Realm SDKs provide client reset modes that automatically handle most client reset errors.
Los modos automáticos de restablecimiento del cliente restauran tu archivo Realm local a un estado de sincronización sin cerrar el realm o perder notificaciones. Los siguientes modos de restablecimiento del cliente admiten restablecimientos automáticos del cliente:
Recuperar el modo de cambios no sincronizados
Recover or discard unsynced changes mode
Discard unsynced changes mode
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.
Client Reset with Recovery
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:
Recuperar el modo de cambios no sincronizados
Recover or discard unsynced changes
Cuando la Recuperación de Cliente está habilitada, estas reglas determinan cómo se integran los objetos, incluyendo la resolución de conflictos cuando tanto el backend como el cliente realizan cambios en el mismo objeto:
Objects created locally that were not synced before client reset are synced.
Si se elimina un objeto en el servidor, pero se modifica en el cliente en recuperación, la eliminación tiene prioridad y el cliente descarta la actualización.
If an object is deleted on the recovering client, but not the server, then the client applies the server's delete instruction.
En el caso de actualizaciones conflictivas en el mismo campo, se aplica la actualización del cliente.
Para obtener más información sobre cómo configurar la Recuperación de cliente, consulte Recuperación de cliente en la documentación de Servicios de aplicaciones.
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.
Para obtener información sobre cambios de esquema disruptivos y no disruptivos, consulte Referencia rápida sobre cambios disruptivos y no disruptivos en la documentación de App Services.
Recover Unsynced Changes Mode
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.
Para manejar los restablecimientos del cliente con el modo recuperar cambios no sincronizados, pasa una ConfiguraciónDeRestablecimientoDeCliente al campo clientReset de tu ConfiguraciónDeSincronizaciónFlexible. Incluye estas propiedades en ClientResetConfiguration:
mode:Establecer en"recoverUnsyncedChanges".onBefore: Optional. Callback function invoked before the SDK executes this mode, when the SDK receives a client reset error from the backend. Provides a copy of the realm.onAfter: opcional. Función de retorno que se activa después de que el SDK ejecuta correctamente este modo. Proporciona instancias del realm antes y después del restablecimiento del cliente.onFallback: Opcional. Función de devolución de llamada que el SDK invoca solo si falla la recuperación automática. Para más información, consulte la sección "Restablecimiento manual del cliente".
The following example implements recover unsynced changes mode:
const syncConfigWithRecoverClientReset = { flexible: true, clientReset: { mode: 'recoverUnsyncedChanges', onBefore: realm => { // This block could be used for custom recovery, reporting, debugging etc. }, onAfter: (beforeRealm, afterRealm) => { // This block could be used for custom recovery, reporting, debugging etc. }, onFallback: (session, path) => { // See below "Manual Client Reset Fallback" section for example }, }, }; function RealmWithRecoverUnsyncedChangesClientReset() { return ( <RealmProvider sync={syncConfigWithRecoverClientReset}> <RestOfApp /> </RealmProvider> ); }
const syncConfigWithRecoverClientReset = { flexible: true, clientReset: { mode: Realm.ClientResetMode.RecoverUnsyncedChanges, onBefore: realm => { // This block could be used for custom recovery, reporting, debugging etc. }, onAfter: (beforeRealm, afterRealm) => { // This block could be used for custom recovery, reporting, debugging etc. }, onFallback: (session, path) => { // See below "Manual Client Reset Fallback" section for example }, }, }; function RealmWithRecoverUnsyncedChangesClientReset() { return ( <RealmProvider sync={syncConfigWithRecoverClientReset}> <RestOfApp /> </RealmProvider> ); }
Recover or Discard Unsynced Changes Mode
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:
mode:Establecer en"recoverOrDiscardUnsyncedChanges".onBefore: Optional. Callback function invoked before the SDK executes this mode, when the SDK receives a client reset error from the backend. Provides a copy of the realm.onAfter: opcional. Función de retorno que se activa después de que el SDK ejecuta correctamente este modo. Proporciona instancias del realm antes y después del restablecimiento del cliente.onFallback(): Opcional. Función de retorno que el SDK invoca solo si tanto la recuperación automática como el descarte de cambios fallan. Para obtener más información, consulte la sección Manual restablecimiento del cliente Fallback.
The following example implements recover unsynced changes mode:
const syncConfigWithRecoverDiscardClientReset = { flexible: true, clientReset: { mode: 'recoverOrDiscardUnsyncedChanges', onBefore: realm => { // This block could be used for custom recovery, reporting, debugging etc. }, onAfter: (beforeRealm, afterRealm) => { // This block could be used for custom recovery, reporting, debugging etc. }, onFallback: (session, path) => { // See below "Manual Client Reset Fallback" section for example }, }, }; function RealmWithRecoverOrDiscardUnsyncedChangesClientReset() { return ( <RealmProvider sync={syncConfigWithRecoverDiscardClientReset}> <RestOfApp /> </RealmProvider> ); }
const syncConfigWithRecoverDiscardClientReset = { flexible: true, clientReset: { mode: Realm.ClientResetMode.RecoverOrDiscardUnsyncedChanges, onBefore: realm => { // This block could be used for custom recovery, reporting, debugging etc. }, onAfter: (beforeRealm, afterRealm) => { // This block could be used for custom recovery, reporting, debugging etc. }, onFallback: (session, path) => { // See below "Manual Client Reset Fallback" section for example }, }, }; function RealmWithRecoverOrDiscardUnsyncedChangesClientReset() { return ( <RealmProvider sync={syncConfigWithRecoverDiscardClientReset}> <RestOfApp /> </RealmProvider> ); }
Manual Client Reset Fallback
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.
Debes proporcionar una implementación manual de restablecimiento del cliente en la función de retorno SyncConfiguration.onFallback(). onFallback() toma dos argumentos:
session:Objeto desesión que representa el estado de la sesión de sincronización del dispositivo.path: String with the path to the current realm file.
El siguiente ejemplo demuestra cómo puedes manejar manualmente este caso de error descartando todos los cambios no sincronizados:
let realm; // value assigned in <RestOfApp> with useRealm() const syncConfigWithClientResetFallback = { flexible: true, clientReset: { mode: 'recoverOrDiscardUnsyncedChanges', // or "recoverUnsyncedChanges" // can also include `onBefore` and `onAfter` callbacks onFallback: (_session, path) => { try { // Prompt user to perform a client reset immediately. If they don't, // 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. const didUserConfirmReset = showUserAConfirmationDialog(); if (didUserConfirmReset) { // Close and delete old realm from device realm.close(); Realm.deleteFile(path); // Perform client reset Realm.App.Sync.initiateClientReset(app, path); // Navigate the user back to the main page or reopen the // the Realm and reinitialize the current page } } catch (err) { // Reset failed. Notify user that they'll need to // update the app } }, }, }; function RealmWithManualClientResetFallback() { return ( <RealmProvider sync={syncConfigWithClientResetFallback}> <RestOfApp /> </RealmProvider> ); } function RestOfApp() { // Assigning variable defined above to a realm. realm = useRealm(); return <>{/* Other components in rest of app */}</>; }
let realm; // value assigned in <RestOfApp> with useRealm() const syncConfigWithClientResetFallback = { flexible: true, clientReset: { mode: Realm.ClientResetMode.RecoverOrDiscardUnsyncedChanges, // or "recoverUnsyncedChanges" // can also include `onBefore` and `onAfter` callbacks onFallback: (_session, path) => { try { // Prompt user to perform a client reset immediately. If they don't, // 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. const didUserConfirmReset = showUserAConfirmationDialog(); if (didUserConfirmReset) { // Close and delete old realm from device realm.close(); Realm.deleteFile(path); // Perform client reset Realm.App.Sync.initiateClientReset(app, path); // Navigate the user back to the main page or reopen the // the Realm and reinitialize the current page } } catch (err) { // Reset failed. Notify user that they'll need to // update the app } }, }, }; function RealmWithManualClientResetFallback() { return ( <RealmProvider sync={syncConfigWithClientResetFallback}> <RestOfApp /> </RealmProvider> ); } function RestOfApp() { // Assigning variable defined above to a realm. realm = useRealm(); return <>{/* Other components in rest of app */}</>; }
Discard Unsynced Changes Mode
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.
El modo Descartar cambios no sincronizados borra permanentemente todos los cambios locales no sincronizados realizados desde la última sincronización exitosa. Puedes usar esta moda cuando tu aplicación requiera una lógica de recuperación de cliente que no sea coherente con Recuperación automática del cliente, o cuando no quieras recuperar datos no sincronizados.
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:
mode:Establecer en"discardUnsyncedChanges".onBefore: Optional. Callback function invoked before the SDK executes this mode, when the SDK receives a client reset error from the backend. Provides a copy of the realm.onAfter: opcional. Función de retorno que se activa después de que el SDK ejecuta correctamente este modo. Proporciona instancias del realm antes y después del restablecimiento del cliente.
El siguiente ejemplo implementa el modo descartar cambios no sincronizados:
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> ); }
Discard Unsynced Changes after Breaking Schema Changes
Si tu aplicación experimenta un cambio de esquema que afecte la compatibilidad, el modo de descartar cambios no sincronizados no puede gestionar automáticamente el restablecimiento resultante del cliente. En cambio, debe proporcionar una implementación de restablecimiento del cliente en la función de retorno de SyncConfiguration error(). El siguiente ejemplo demuestra cómo se puede gestionar manualmente este caso de error descartando todos los cambios no sincronizados:
// Once you have opened your Realm, you will have to keep a reference to it. // In the error handler, this reference is called `realm` async function handleSyncError(session, syncError) { if (syncError.name == 'ClientReset') { console.log(syncError); try { console.log('error type is ClientReset....'); const path = realm.path; // realm.path will not be accessible after realm.close() realm.close(); Realm.App.Sync.initiateClientReset(app, path); // Download Realm from the server. // Ensure that the backend state is fully downloaded before proceeding, // which is the default behavior. realm = await Realm.open(config); realm.close(); } catch (err) { console.error(err); } } else { // ...handle other error types } } const syncConfigWithDiscardAfterBreakingSchemaChanges = { flexible: true, clientReset: { mode: 'discardUnsyncedChanges', onBefore: realm => { // NOT used with destructive schema changes console.log('Beginning client reset for ', realm.path); }, onAfter: (beforeRealm, afterRealm) => { // Destructive schema changes do not hit this function. // Instead, they go through the error handler. console.log('Finished client reset for', beforeRealm.path); console.log('New realm path', afterRealm.path); }, }, onError: handleSyncError, // invoked with destructive schema changes }; function RealmWitDiscardAfterBreakingSchemaChangesClientReset() { return ( <RealmProvider sync={syncConfigWithDiscardAfterBreakingSchemaChanges}> <RestOfApp /> </RealmProvider> ); }
// Once you have opened your Realm, you will have to keep a reference to it. // In the error handler, this reference is called `realm` async function handleSyncError(session, syncError) { if (syncError.name == 'ClientReset') { console.log(syncError); try { console.log('error type is ClientReset....'); const path = realm.path; // realm.path will not be accessible after realm.close() realm.close(); Realm.App.Sync.initiateClientReset(app, path); // Download Realm from the server. // Ensure that the backend state is fully downloaded before proceeding, // which is the default behavior. realm = await Realm.open(config); realm.close(); } catch (err) { console.error(err); } } else { // ...handle other error types } } const syncConfigWithDiscardAfterBreakingSchemaChanges = { flexible: true, clientReset: { mode: Realm.ClientResetMode.DiscardUnsyncedChanges, onBefore: realm => { // NOT used with destructive schema changes console.log('Beginning client reset for ', realm.path); }, onAfter: (beforeRealm, afterRealm) => { // Destructive schema changes do not hit this function. // Instead, they go through the error handler. console.log('Finished client reset for', beforeRealm.path); console.log('New realm path', afterRealm.path); }, }, onError: handleSyncError, // invoked with destructive schema changes }; function RealmWitDiscardAfterBreakingSchemaChangesClientReset() { return ( <RealmProvider sync={syncConfigWithDiscardAfterBreakingSchemaChanges}> <RestOfApp /> </RealmProvider> ); }
Nota
Descartar con Recuperación
If you'd like to attempt to recover unsynced changes, but but discard any changes that cannot be recovered, refer to the recover or discard unsynced changes mode section.
Manual Mode
Changed in version realm@10.23.0: onManual callback added
En el modo manual, defines tu propio handler de restablecimiento del cliente. Tal vez quieras usar un handler de restablecimiento del cliente manual si la lógica de recuperación automática no funciona para tu aplicación y no puedes descartar los datos locales no sincronizados.
Para manejar los restablecimientos del cliente en modo manual, pasa una ClientResetConfiguration al campo clientReset de tu FlexibleSyncConfiguration. Incluye estas propiedades en el ClientResetConfiguration:
mode:Establecer en"manual".onManual: Opcional. Función de devolución de llamada que se invoca al reiniciar el cliente. Proporciona información sobre la sesión de sincronización y la ruta al dominio actual. Si no se configura el controlador de erroresonManual, el error de reinicio del cliente se revierte al controlador de errores de sincronización general.
const syncConfigWithManualClientReset = { flexible: true, clientReset: { mode: 'manual', onManual: (session, path) => { // handle manual client reset here }, }, }; function RealmWitManualClientReset() { return ( <RealmProvider sync={syncConfigWithManualClientReset}> <RestOfApp /> </RealmProvider> ); }
const syncConfigWithManualClientReset = { flexible: true, clientReset: { mode: 'manual', onManual: (session, path) => { // handle manual client reset here }, }, }; function RealmWitManualClientReset() { return ( <RealmProvider sync={syncConfigWithManualClientReset}> <RestOfApp /> </RealmProvider> ); }
Recuperación manual de datos
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.
Test Client Reset Handling
Puede probar manualmente el manejo de restablecimiento del cliente de su aplicación finalizando y volviendo a habilitar la sincronización del dispositivo.
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:
Write data from a client application and wait for it to synchronize.
Termina y vuelve a habilitar Device Sync.
Ejecuta la aplicación cliente nuevamente. La aplicación debería obtener un error de restablecimiento del cliente cuando intente conectarse al servidor.
Advertencia
Mientras itera sobre la gestión del restablecimiento de clientes en su aplicación cliente, es posible que tenga que finalizar y volver a habilitar la sincronización repetidamente. Esto impide que todos los clientes existentes puedan sincronizar hasta después de completar un restablecimiento. Para evitar esto en producción, pruebe la gestión del restablecimiento de clientes en un entorno de desarrollo.