Manejar errores de sincronización
Al desarrollar una aplicación que use Sincronización de Dispositivos, debe configurar un controlador de errores. Este controlador detectará y responderá a cualquier llamada a la API relacionada con la sincronización fallida.
Tip
Para obtener una lista de errores comunes de sincronización de dispositivos y cómo solucionarlos, consulte Errores de sincronización en la documentación de sincronización de dispositivos de App Services.
Establezca un controlador de errores en el singleton RLMSyncManager. Cuando se produce un error, el SDK de Swift llama al controlador de errores con el objeto de error y la sesión RLMSyncSession donde se produjo el error.
Nota
Realm representa los errores de sincronización mediante objetos NSError cuyo dominio es RLMSyncErrorDomain. Para obtener más información sobre los códigos de error, consulte las definiciones de RLMSyncError y RLMSyncAuthError.
RLMApp *app = [RLMApp appWithId:YOUR_APP_ID]; // Access the sync manager for the app RLMSyncManager *syncManager = [app syncManager]; syncManager.errorHandler = ^(NSError *error, RLMSyncSession *session) { // handle error };
Establezca un controlador de errores en el singleton SyncManager. Cuando se produce un error, el SDK de Swift llama al controlador de errores con el objeto de error y la sesión de sincronización donde se produjo el error.
Nota
SyncError de Realm se ajusta al protocolo de errores de Swift
let app = App(id: YOUR_APP_SERVICES_APP_ID) app.syncManager.errorHandler = { error, session in // handle error }
Tip
Para obtener información sobre cómo configurar un nivel de registro de cliente o personalizar el registrador, consulte Establecer el nivel de registro de cliente - Swift SDK.
Restablecimiento del cliente
Al usar la Sincronización de Dispositivos, el restablecimiento del cliente es una tarea de recuperación de errores que la aplicación cliente debe realizar cuando un dominio sincronizado en el servidor ya no puede sincronizarse con el dominio del cliente. En este caso, el cliente debe restablecer su dominio a un estado que coincida con el del servidor para poder restablecer la sincronización.
Cuando esto ocurre, el dominio no sincronizable del cliente puede contener datos que aún no se han sincronizado con el servidor. Los SDK de dominio pueden intentar recuperar o descartar esos datos durante el proceso de restablecimiento del cliente.
Para obtener más información sobre qué podría provocar que se restablezca un cliente, vaya a Restablecimientos de cliente en la documentación de Servicios de aplicaciones.
Reinicio automático vs. manual del cliente
Los SDK de Realm ofrecen modos de restablecimiento de cliente que gestionan automáticamente la mayoría de los errores de restablecimiento. Los modos de restablecimiento automático de cliente restauran el archivo local de Realm a un estado sincronizable sin cerrarlo ni perder notificaciones.
Todos los modos de reinicio del cliente excepto .manual Realizar un restablecimiento automático del cliente. Las diferencias entre los modos se basan en cómo gestionan los cambios en el dispositivo que aún no se han sincronizado con el backend.
Elige .recoverUnsyncedChanges para gestionar automáticamente la mayoría de los escenarios de restablecimiento del cliente. Esto intenta recuperar los cambios no sincronizados cuando ocurre un restablecimiento del cliente.
En algunos casos, puede que quieras o necesites configurar un controlador de reinicio manual del cliente. Esto es recomendable si tu aplicación requiere una lógica de reinicio específica que no se puede gestionar automáticamente.
Especificar un modo de reinicio del cliente
Cambiado en la versión: Se agregó 10.32.0 recuperación de cliente, se cambió el nombre de discardLocal
El SDK de Swift ofrece la opción de especificar un modo de restablecimiento de cliente en SyncConfiguration.Esta es la propiedad `.clientResetMode`.
// Specify the clientResetMode when you create the SyncConfiguration. // If you do not specify, this defaults to `.recoverUnsyncedChanges` mode. var configuration = user.flexibleSyncConfiguration(clientResetMode: .recoverUnsyncedChanges())
Esta propiedad toma una enumeración que representa los diferentes modos de reinicio del cliente:
.recoverUnsyncedChanges.recoverOrDiscardUnsyncedChanges.discardUnsyncedChanges.manual
Si no especifica .clientResetMode en su configuración, el modo de restablecimiento del cliente predeterminado será .recoverUnsyncedChanges.
Puede especificar un bloque before y after para que se ejecute durante el proceso de restablecimiento automático del cliente. Puede usarlo para ejecutar la lógica de recuperación importante para su aplicación.
// A block called after a client reset error is detected, but before the // client recovery process is executed. // This block could be used for any custom logic, reporting, debugging etc. // This is one example, but your usage may vary. let beforeClientResetBlock: (Realm) -> Void = { before in var recoveryConfig = Realm.Configuration() recoveryConfig.fileURL = myRecoveryPath do { try before.writeCopy(configuration: recoveryConfig) // The copied realm could be used later for recovery, debugging, reporting, etc. } catch { // handle error } } // A block called after the client recovery process has executed. // This block could be used for custom recovery, reporting, debugging etc. // This is one example, but your usage may vary. let afterClientResetBlock: (Realm, Realm) -> Void = { before, after in // let res = after.objects(myClass.self) // if (res.filter("primaryKey == %@", object.primaryKey).first != nil) { // // ...custom recovery logic... // } else { // // ...custom recovery logic... // } // } } do { let app = App(id: YOUR_APP_SERVICES_APP_ID) let user = try await app.login(credentials: Credentials.anonymous) var configuration = user.flexibleSyncConfiguration(clientResetMode: .recoverOrDiscardUnsyncedChanges( beforeReset: beforeClientResetBlock, afterReset: afterClientResetBlock)) } catch { print("Error logging in user: \(error.localizedDescription)") }
Si su aplicación tiene necesidades específicas de recuperación de clientes, puede especificar el .manual modo de restablecimiento de cliente y configurar un controlador manual de restablecimiento de cliente. Puede hacerlo si su aplicación debe ejecutar una lógica personalizada específica durante un restablecimiento de cliente o si las reglas de recuperación de cliente no funcionan.
Nota
Si su aplicación utiliza la versión 10.24.2 o anterior del SDK de Swift, .clientResetMode no es una propiedad disponible en SyncConfiguration.
Manejar cambios de esquema
La Recuperación de Cliente es una función que se habilita de forma predeterminada al configurar la Sincronización de Dispositivos. Cuando está habilitada, Realm puede administrar automáticamente el proceso de restablecimiento del cliente en la mayoría de los casos. Al realizar cambios en el esquema:
El cliente puede recuperar cambios no sincronizados cuando no hay cambios de esquema o cambios de esquema que no interrumpan el proceso.
Al realizar cambios de esquema disruptivos, los modos de restablecimiento automático del cliente recurren a un gestor de errores manual. Puede configurar un gestor de errores de restablecimiento manual del cliente para este caso. La recuperación automática del cliente no puede ocurrir cuando su aplicación realiza cambios de esquema disruptivos.
Para obtener información sobre cambios de esquema disruptivos y no disruptivos, consulte Referencia rápida sobre cambios disruptivos y no disruptivos.
Recuperar cambios no sincronizados
Nuevo en la versión 10.32.0.
Durante un restablecimiento de cliente, las aplicaciones cliente pueden intentar recuperar datos del dominio local que aún no se hayan sincronizado con el backend. Para recuperar los cambios no sincronizados, laRecuperación de Cliente debe estar habilitada en la aplicación de Servicios de Aplicaciones, como está predeterminado.
Si desea que su aplicación recupere los cambios que aún no se han sincronizado, configure .clientResetMode en SyncConfiguration en uno de los siguientes:
.recoverUnsyncedChangesAl seleccionar este modo, el cliente intenta recuperar los cambios no sincronizados. Elija este modo si no desea descartar los cambios no sincronizados..recoverOrDiscardUnsyncedChangesEl cliente primero intenta recuperar los cambios que aún no se han sincronizado. Si no puede recuperar los datos no sincronizados, descarta los cambios no sincronizados, pero continúa reiniciando el cliente automáticamente. Seleccione este modo si desea habilitar la recuperación automática del cliente para descartar los cambios no sincronizados.
// Specify the clientResetMode when you create the SyncConfiguration. // If you do not specify, this defaults to `.recoverUnsyncedChanges` mode. var configuration = user.flexibleSyncConfiguration(clientResetMode: .recoverUnsyncedChanges())
Es posible que, en ocasiones, la operación de restablecimiento del cliente no pueda completarse en el modo de recuperación de cambios no sincronizados, como cuando hay cambios de esquema importantes o la recuperación del cliente está deshabilitada en la configuración de sincronización de dispositivos. Para solucionar este problema, la aplicación puede implementar una alternativa de restablecimiento manual del cliente.
Reglas de recuperación del cliente
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:
Se sincronizan los objetos creados localmente que no se sincronizaron antes del reinicio del cliente.
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.
Si se elimina un objeto en el cliente en recuperación, pero no en el servidor, el cliente aplica la instrucción de eliminación del servidor.
En el caso de actualizaciones conflictivas en el mismo campo, se aplica la actualización del cliente.
Descartar cambios no sincronizados
Cambiado en la 10.32.0 versión: .discardLocal cambió a .discardUnsyncedChanges
El modo de restablecimiento del cliente para descartar cambios no sincronizados elimina permanentemente todos los cambios locales no sincronizados realizados desde la última sincronización exitosa. Puedes usar este modo cuando tu aplicación requiere una lógica de recuperación del cliente que no coincide con las reglas de recuperación del cliente de sincronización de dispositivos o cuando no deseas recuperar datos no sincronizados.
No utilice el modo de descartar cambios no sincronizados si su aplicación no puede perder datos locales que aún no se han sincronizado con el backend.
Para realizar un restablecimiento automático del cliente que descarte los cambios no sincronizados, configure .clientResetMode en SyncConfiguration .discardUnsyncedChanges en.
do { let app = App(id: APP_ID) let user = try await app.login(credentials: Credentials.anonymous) var config = user.flexibleSyncConfiguration(clientResetMode: .discardUnsyncedChanges()) } catch { print("Error logging in user: \(error.localizedDescription)") }
Nota
Descartar con recuperación
Si desea intentar recuperar cambios no sincronizados, pero descartar cualquier cambio que no se pueda recuperar, consulte la .recoverOrDiscardUnsyncedChanges documentación en Recuperar cambios no sincronizados.
Puede haber ocasiones en las que la operación de restablecimiento del cliente no pueda completarse en el modo de descartar cambios no sincronizados, como cuando hay cambios de esquema importantes. Para solucionar este caso, la aplicación puede implementar una alternativa de restablecimiento manual del cliente.
Modo de restablecimiento manual del cliente
Cuando especifica .manual para .clientResetMode, debe implementar un controlador de restablecimiento de cliente manual.
En .manual el modo, define su propio controlador de restablecimiento de cliente. Este controlador puede aceptar un valor.ErrorReportingBlock Recomendamos usar los modos de recuperación automática del cliente siempre que sea posible y elegir el .manual modo solo si la lógica de recuperación automática no es adecuada para su aplicación.
do { let app = App(id: APP_ID) let user = try await app.login(credentials: Credentials.anonymous) var config = user.flexibleSyncConfiguration(clientResetMode: .manual()) } catch { print("Error logging in user: \(error.localizedDescription)") }
Tip
Si está utilizando una versión anterior del SDK y desea ver un ejemplo de cómo podría recuperar manualmente los cambios en un restablecimiento manual del cliente, consulte este ejemplo en GitHub.
Restablecimiento manual del cliente
Si la operación de restablecimiento del cliente no puede completarse automáticamente, como cuando se producen cambios importantes en el esquema, el proceso se redirige a un gestor de errores manual. Esto puede ocurrir en cualquiera de estos modos de restablecimiento automático del cliente:
.recoverUnsyncedChanges.recoverOrDiscardUnsyncedChanges.discardUnsyncedChanges
Puede configurar un controlador de errores para este caso de respaldo mediante la instancia de RLMSyncManager en su RLMApp. Recomendamos usar el controlador manual como herramienta para situaciones de recuperación de errores fatales en las que se recomienda a los usuarios actualizar la aplicación o realizar alguna otra acción.
RLMApp *app = [RLMApp appWithId:YOUR_APP_ID]; [[app syncManager] setErrorHandler:^(NSError *error, RLMSyncSession *session) { if (error.code == RLMSyncErrorClientResetError) { // TODO: Invalidate all open realm instances // TODO: Restore the local changes backed up at [error rlmSync_clientResetBackedUpRealmPath] [RLMSyncSession immediatelyHandleError:[error rlmSync_errorActionToken] syncManager:[app syncManager]]; return; } // Handle other errors... }];
Puede configurar un controlador de errores para este caso de respaldo mediante SyncManager. Recomendamos usar el controlador manual como herramienta para situaciones de recuperación de errores fatales en las que se recomienda a los usuarios actualizar la aplicación o realizar alguna otra acción.
func handleClientReset() { // Report the client reset error to the user, or do some custom logic. } do { let app = App(id: APP_ID) let user = try await app.login(credentials: Credentials.anonymous) var config = user.flexibleSyncConfiguration(clientResetMode: .recoverOrDiscardUnsyncedChanges()) // If client recovery fails, app.syncManager.errorHandler = { error, session in guard let syncError = error as? SyncError else { fatalError("Unexpected error type passed to sync error handler! \(error)") } switch syncError.code { case .clientResetError: if let (path, clientResetToken) = syncError.clientResetInfo() { handleClientReset() SyncSession.immediatelyHandleError(clientResetToken, syncManager: app.syncManager) } default: // Handle other errors... () } } } catch { print("Error: \(error.localizedDescription)") }
Manejo del restablecimiento del cliente de prueba
Puede probar manualmente el manejo de restablecimiento del cliente de su aplicación finalizando y volviendo a habilitar la sincronización del dispositivo.
Al finalizar y reactivar Sync, los clientes que se conectaron previamente con Sync no podrán hacerlo hasta que restablezcan el cliente. Al finalizar Sync, se eliminan los metadatos del servidor que permiten la sincronización. El cliente debe descargar una nueva copia del dominio desde el servidor. El servidor envía un error de restablecimiento de cliente a estos clientes. Por lo tanto, al finalizar Sync, se activa la condición de restablecimiento de cliente.
Para probar el manejo del restablecimiento del cliente:
Escriba datos desde una aplicación cliente y espere a que se sincronicen.
Termina y vuelve a habilitar Device Sync.
Ejecute la aplicación cliente nuevamente. La aplicación debería mostrar un error de restablecimiento de cliente al intentar 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.