Lidar com erros de sincronização - Swift SDK
Nesta página
- Gerenciar erros de sincronização
- Reinício do cliente
- reinício do cliente automático versus manual
- Especificar um modo de reinício do cliente
- Lidar com alterações no esquema
- Recuperar alterações não sincronizadas
- Descartar alterações não sincronizadas
- Modo de reinício do cliente
- fallback de reinício do cliente
- Tratamento de reinício do cliente de teste
Gerenciar erros de sincronização
Ao desenvolver uma aplicação que usa o Realm Mobile Sync, você deve definir um manipulador de erros. Esse manipulador de erros detectará e responderá a quaisquer chamadas de API relacionadas à sincronização com falha.
Dica
Para obter uma lista de erros comuns do Device Sync e como gerenciá-los, consulte Erros do Sync na documentação do App Services Device Sync .
Defina um manipulador de erro no singleton RLMSyncManager . Quando ocorre um erro, o Swift SDK chama o manipulador de erro com o objeto de erro e a RLMSyncSession em que o erro ocorreu.
Observação
O Realm representa erros de sincronização por meio de objetos NSError cujo domínio é RLMSyncErrorDomain. Para saber mais sobre os códigos de erro, consulte as definições de RLMSyncError e 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 };
Defina um manipulador de erros no singleton do SyncManager . Defina um manipulador de erros no singleton do SyncManager. Quando ocorre um erro, o Swift SDK chama o manipulador de erro com o objeto de erro e a SyncSession em que o erro ocorreu.
Observação
O SyncError da Realm está em conformidade com o protocolo de erro da Swift
let app = App(id: YOUR_APP_SERVICES_APP_ID) app.syncManager.errorHandler = { error, session in // handle error }
Dica
Veja também:
Para obter informações sobre como definir um nível de registro do cliente ou personalizar o registrador, consulte Definir o nível de registro do cliente - Swift SDK.
Reinício do cliente
Ao usar o Device Sync, um reinício do cliente é uma tarefa de recuperação de erros que seu aplicativo cliente deve executar quando um determinado Realm sincronizado no servidor não puder mais ser sincronizado com o Realm do cliente . Nesse caso, o cliente deve redefinir seu Realm para um estado que corresponda ao servidor para restaurar a capacidade de sincronização.
Quando isso ocorre, o Realm não sincronizável no cliente pode conter dados que ainda não foram sincronizados com o servidor. Os SDKs do Realm podem tentar recuperar ou descartar esses dados durante o processo de reinício do cliente.
Para obter mais informações sobre o que pode causar a ocorrência de um reinício do cliente, Go Redefinições do cliente na documentação do Atlas App Services .
reinício do cliente automático versus manual
Os SDKs do Realm oferecem modos de reinício do cliente que gerenciam automaticamente a maioria dos erros de reinício do cliente. Os modos automáticos de reinício do cliente restauram seu arquivo de domínio local para um estado sincronizável sem fechar o domínio ou perder notificações.
Todos os modos de reinício do cliente, exceto .manual
, executam um reinício do cliente automático. As diferenças entre os modos são baseadas em como eles lidam com alterações no dispositivo que ainda não foram sincronizadas com o backend.
Escolha .recoverUnsyncedChanges
para lidar com a maioria dos cenários de reinício do cliente automaticamente. Isso tenta recuperar alterações não sincronizadas quando ocorre um reinício do cliente.
Em alguns casos, você pode desejar ou precisar definir um manipulador manual de redefinição do cliente. Talvez você queira fazer isso se o seu aplicativo exigir lógica de redefinição de cliente específica que não possa ser tratada automaticamente.
Especificar um modo de reinício do cliente
Alterado na versão 10,32,0: Recuperação do cliente adicionada, nome do descartarLocal alterado
O Swift SDK oferece a opção de especificar um modo de reinício do cliente em seu SyncConfiguration. Este é o .clientResetMode propriedade.
// 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 propriedade usa um enumeração que representa os diferentes modos de reinício do cliente :
.recoverUnsyncedChanges
.recoverOrDiscardUnsyncedChanges
.discardUnsyncedChanges
.manual
Se você não especificar .clientResetMode
em sua configuração, o modo de reinício do cliente será padronizado como .recoverUnsyncedChanges
.
Você pode especificar um bloco before
e after
para ser executado durante o processo automático de reinício do cliente. Você pode usar isso para executar a lógica de recuperação que é importante para seu aplicativo.
// 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)") }
Se seu aplicativo tiver necessidades específicas de recuperação do cliente, você poderá especificar o modo de reinício do cliente .manual
e definir um manipulador manual de reinício do cliente. Você pode fazer isso se tiver uma lógica personalizada específica que seu aplicativo deve executar durante a redefinição de um cliente ou se as regras de recuperação do cliente não funcionarem para seu aplicativo.
Observação
Se o seu aplicativo utilizar o Swift SDK versão 10.24.2 ou anterior, .clientResetMode
não será uma propriedade disponível no SyncConfiguration
.
Lidar com alterações no esquema
A recuperação de cliente é um recurso que é habilitado por padrão quando você configura o Device Sync. Quando a Recuperação de Cliente está ativada, o Realm pode gerenciar automaticamente o processo de redefinição do cliente na maioria dos casos. Quando você faz alterações no esquema:
O cliente pode recuperar alterações não sincronizadas quando não houver alterações no esquema ou alterações no esquema não significativas.
Quando você faz alterações significativas no esquema, os modos automáticos de reinício do cliente voltam para um manipulador manual de erros. Você pode definir um manipulador de erro de redefinição manual do cliente para esse caso. A recuperação automática do cliente não pode ocorrer quando seu aplicativo faz alterações significativas no esquema.
Para obter informações sobre alterações de esquema significativas e não significativas, consulte Referência rápida de alterações significativas versus não significativas.
Recuperar alterações não sincronizadas
Novidade na versão 10.32.0.
Durante um reinício do cliente do cliente , os aplicativos do cliente podem tentar recuperar dados no Realm local que ainda não foram sincronizados com o backend. Para recuperar alterações não sincronizadas, a Recuperação de cliente deve estar ativada em seu App Services App, como é por padrão.
Se você quiser que seu aplicativo recupere as alterações que ainda não foram sincronizadas, defina .clientResetMode em SyncConfiguration como um dos seguintes:
.recoverUnsyncedChanges
: ao escolher esse modo, o cliente tenta recuperar alterações não sincronizadas. Escolha este modo se não quiser descartar alterações não sincronizadas..recoverOrDiscardUnsyncedChanges
: o cliente primeiro tenta recuperar as alterações que ainda não foram sincronizadas. Se o cliente não conseguir recuperar dados não sincronizados, ele falhará no descarte das alterações não sincronizadas, mas continuará executando automaticamente o reinício do cliente. Escolha este modo quando quiser ativar a recuperação automática do cliente para voltar a descartar alterações não sincronizadas.
// Specify the clientResetMode when you create the SyncConfiguration. // If you do not specify, this defaults to `.recoverUnsyncedChanges` mode. var configuration = user.flexibleSyncConfiguration(clientResetMode: .recoverUnsyncedChanges())
Pode haver momentos em que a operação de redefinição do cliente não pode ser concluída no modo de recuperação de alterações não sincronizadas, como quando há alterações de esquema de quebra ou a Recuperação de Cliente está desabilitada na configuração do Device Sync. Para lidar com esse caso, seu aplicativo pode implementar um fallback manual de redefinição do cliente.
Regras de recuperação do cliente
Quando a Recuperação de Cliente está habilitada, essas regras determinam como os objetos são integrados, incluindo como os conflitos são resolvidos quando o backend e o cliente fazem alterações no mesmo objeto:
Objetos criados localmente que não foram sincronizados antes da redefinição do cliente são sincronizados.
Se um objeto for excluído no servidor, mas for modificado no cliente de recuperação, a exclusão terá precedência e o cliente descartará a atualização.
Se um objeto for excluído no cliente em recuperação, mas não no servidor, o cliente aplicará a instrução de exclusão do servidor.
No caso de atualizações conflitantes no mesmo campo, a atualização do cliente é aplicada.
Descartar alterações não sincronizadas
Alterado na versão 10.32.0: .discardLocal alterado para .discardUnsyncedChanges
O modo de reinício do cliente de descarte de alterações não sincronizadas exclui permanentemente todas as alterações não sincronizadas locais feitas desde a última sincronização bem-sucedida. Você pode usar esse modo quando seu aplicativo exigir uma lógica de recuperação de cliente que não seja consistente com as Regras de recuperação de cliente do Device Sync ou quando você não quiser recuperar dados não sincronizados.
Não use o modo de descarte de alterações não sincronizadas se o aplicativo não puder perder dados locais que ainda não foram sincronizados com o backend.
Para executar um reinício do cliente automático que descarta alterações não sincronizadas, defina o .clientResetMode em SyncConfiguration como .discardUnsyncedChanges
.
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)") }
Observação
Descartar com recuperação
Se você quiser tentar recuperar as alterações não sincronizadas, mas descartar todas as alterações que não podem ser recuperadas, consulte a documentação .recoverOrDiscardUnsyncedChanges
em Recuperar alterações não sincronizadas.
Pode haver momentos em que a operação de reinício do cliente não pode ser concluída no modo de descarte de alterações não sincronizadas, como quando há alterações de esquema significativas. Para lidar com esse caso, seu aplicativo pode implementar um fallback manual de redefinição do cliente.
Modo de reinício do cliente
Ao especificar .manual
para .clientResetMode
, você deve implementar um manipulador manual de reinício do cliente.
No modo .manual
, você define seu próprio manipulador de reinício do cliente . O manipulador pode receber um ErrorReportingBlock
. Recomendamos usar os modos de recuperação automática de cliente quando possível e escolher o modo .manual
somente se a lógica de recuperação automática não for adequada para seu aplicativo.
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)") }
Dica
Se você estiver usando uma versão mais antiga do SDK e quiser ver um exemplo de como recuperar manualmente as alterações em uma reinício do cliente, confira este exemplo no Github.
fallback de reinício do cliente
Se a operação de reinício do cliente não puder ser concluída automaticamente, como quando há alterações de esquema de quebra, o processo de reinício do cliente passará para um manipulador de erros manual. Isso pode ocorrer em qualquer um destes modos automáticos de reinício do cliente:
.recoverUnsyncedChanges
.recoverOrDiscardUnsyncedChanges
.discardUnsyncedChanges
Você pode definir um manipulador de erro para esse caso fallback por meio da instância RLMSyncManager em seu RLMApp. Recomendamos tratar o manipulador manual como uma ferramenta para situações de recuperação de erros fatais em que você aconselha os usuários a atualizar o aplicativo ou executar alguma outra ação.
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... }];
Você pode definir um manipulador de erro para esse caso alternativo por meio do SyncManager. Recomendamos tratar o manipulador manual como uma ferramenta para situações de recuperação de erros fatais em que você aconselha os usuários a atualizar o aplicativo ou executar alguma outra ação.
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)") }
Tratamento de reinício do cliente de teste
Você pode testar manualmente o tratamento de redefinição do cliente do seu aplicativo encerrando e reativando o Device Sync.
Quando você encerra e reativa a sincronização, os clientes que se conectaram anteriormente à sincronização não conseguem se conectar até depois de fazerem um reinício do cliente. O encerramento da sincronização exclui os metadados do servidor que permitem ao cliente sincronizar. O cliente deve baixar uma nova cópia do Realm do servidor. O servidor envia um erro de reinício do cliente para esses clientes. Então, ao encerrar a sincronização, você trigger a condição de reinício do cliente.
Para testar o tratamento de reinício do cliente:
Escreva dados de um aplicativo cliente e aguarde a sincronização.
Encerre e reative o Realm Mobile Sync.
Run the client app again. O aplicativo deve receber um erro de reinício do cliente ao tentar se conectar ao servidor.
Aviso
Enquanto você itera sobre o tratamento de redefinição do cliente em seu aplicativo cliente, talvez seja necessário encerrar e reativar a sincronização repetidamente. Encerrar e reativar a sincronização impede que todos os clientes existentes sincronizem até depois de concluir a redefinição do cliente. Para evitar isso na produção, teste o tratamento de redefinição do cliente em um ambiente de desenvolvimento.