Lidar com erros de sincronização - Kotlin SDK
Nesta página
- Gerenciar erros de sincronização
- Exceções de sincronização
- Erros de sincronização irrecuperáveis
- Erros de tipo de sincronização incorreto
- Erros de query de Flexible Sync incorretos
- Lidar com erros de reinício do cliente
- Estratégias de reinício do cliente
- Reinício do cliente automático versus manual
- Redefinição do cliente com recuperação
- Especificar uma estratégia de reinício do cliente
- Recuperar ou descartar alterações não sincronizadas
- Recuperar alterações não sincronizadas
- Descartar alterações não sincronizadas
- fallback de recuperação manual
- Recuperar manualmente alterações não sincronizadas
- Tratamento de reinício do cliente de teste
Ao desenvolver um aplicação que usa o Device Sync, você deve definir um manipulador de erros. Esse manipulador de erros detectará e responderá a qualquer chamada de API relacionada à sincronização com falha.
Dica
Para obter uma lista de erros comuns do Device Sync e como gerenciá-los, consulte Erros de sincronização na documentação do Atlas App Services Device Sync .
Gerenciar erros de sincronização
Defina um manipulador de erro por meio do SyncConfiguration.errorHandler propriedade ao criar um domínio sincronizado. Quando ocorre um erro, o Kotlin SDK chama o manipulador de erro com o objeto de erro e a SyncSession em que o erro ocorreu.
Se você não especificar um manipulador de erros, o comportamento padrão será imprimir o erro de sincronização no console.
val syncErrorHandler = SyncSession.ErrorHandler { session, error -> Log.e("Error message" + error.message.toString()) } runBlocking { val user = app.login(credentials) val config = SyncConfiguration.Builder(user, setOf(Toad::class)) .initialSubscriptions { realm -> add(realm.query<Toad>(), "subscription name") } .errorHandler(syncErrorHandler) // Specify a sync error handler .build() // Proceed to open a realm... }
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 - Kotlin SDK.
Exceções de sincronização
Uma SyncException é uma subclasse de AppException. Um SyncException
ocorre quando o Device Sync falha.
Para obter mais informações sobre exceções de aplicativos, consulte Gerenciar erros de aplicativos.
Erros de sincronização irrecuperáveis
Uma UnrecoverableSyncException ocorre quando o Device Sync falha catastroficamente. Isso geralmente significa um bug no cliente ou no aplicativo conectado.
Quando ocorre um erro de sincronização irrecuperável, você deve apresentar o problema ao usuário final. Informe a eles que o Realm Mobile Sync não funcionará até que o problema seja resolvido. É melhor enviar um alerta a você mesmo para poder verificar os registros do aplicativo de backend e corrigir o problema o mais rápido possível.
Erros de tipo de sincronização incorreto
Uma WrongSyncTypeException ocorre quando o cliente e o aplicativo usam protocolos de sincronização diferentes.
O SDK oferece suporte a dois tipos de sincronização: sincronização flexível e sincronização baseada em partição . Quando um cliente se conecta a um aplicativo usando um tipo de sincronização que não corresponde ao tipo de sincronização do aplicativo, ocorre um erro de tipo de sincronização incorreto.
Para recuperar de um erro de tipo de sincronização incorreto, atualize o cliente para usar um tipo de sincronização que corresponda ao backend. Isso provavelmente exigirá que o usuário atualize para uma nova versão do seu aplicativo contendo a correção.
Erros de query de Flexible Sync incorretos
Uma Exceção de definiçãoBadFlexibleSyncQuery ocorre quando você tenta assinar uma consulta de sincronização flexível que não é suportada pelo backend do aplicativo. Isso pode acontecer quando você:
query de um campo não especificado como um campo de query em sua configuração de Flexible Sync
criar uma query de Flexible Sync usando operadores não suportados pelo Flexible Sync
Para se recuperar de um erro grave de Flexible Sync, atualize seu cliente para usar uma query de sincronização compatível com a configuração da sua aplicação. Isso provavelmente exigirá que o usuário atualize para uma nova versão do seu aplicativo contendo a correção.
Lidar com erros de 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 o servidor do Device Sync não puder mais sincronizar com o domínio do cliente. Nesse caso, o cliente deve redefinir seu domínio 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 .
Estratégias de reinício do cliente
Os SDKs do Realm oferecem estratégias de redefinição do cliente que lidam automaticamente com a maioria dos erros de redefinição do cliente, bem como uma estratégia de recuperação manual.
Reinício do cliente automático versus manual
Estratégias de reinício automático restauram seu arquivo de Realm local para um estado sincronizável sem fechar o Realm ou perder notificações. As diferenças são baseadas em como eles lidam com alterações no dispositivo que ainda não foram sincronizadas com o backend. As estratégias a seguir implementam a interface AutomaticClientResetStrategy e oferecem suporte ao reinício do cliente automático:
Recuperar ou descartar alterações não sincronizadas (padrão): o manipulador de reinício do cliente primeiro tenta recuperar as alterações não sincronizadas. Se a recuperação falhar, esse manipulador voltará para a estratégia de descarte de alterações não sincronizadas, que exclui permanentemente todas as alterações locais não sincronizadas. Se a estratégia de descartar alterações não sincronizadas falhar, o manipulador voltará para a recuperação manual.
Recuperar alterações não sincronizadas: o manipulador de redefinição do cliente primeiro tenta recuperar alterações não sincronizadas. Se a recuperação falhar, esse manipulador voltará para a recuperação manual.
Descartar alterações não sincronizadas: essa estratégia exclui permanentemente todas as alterações não sincronizadas locais feitas desde a última sincronização bem-sucedida. Se o descarte falhar, esse manipulador voltará para a recuperação manual. Este modo é recomendado para lidar com qualquer recuperação manual de dados.
Se o seu aplicativo exigir uma lógica específica de redefinição do cliente que não possa ser tratada automaticamente, convém ou precise adicionar um manipulador manual de redefinição do cliente usando a interface ManuallyRecoverUnsyncedChangesStrategy :
Recuperar manualmente alterações não sincronizadas: permite que você implemente sua própria estratégia de recuperação manual. A recuperação manual é a única estratégia que não executa um reinício do cliente automático . Este modo permite que você faça backup apenas do seu Realm . Recomendamos usar a estratégia de descartar alterações não sincronizadas para lidar com a recuperação manual, se possível.
Redefinição do cliente com recuperação
A recuperação de cliente é um recurso que é habilitado por padrão quando você configura o Device Sync.
Para usar a Recuperação de Cliente, configure seu Realm com a estratégia de recuperar alterações não sincronizadas ou recuperar ou descartar alterações não sincronizadas , e o Realm gerencia automaticamente o processo de reinício do cliente na maioria dos casos:
O cliente pode recuperar alterações não sincronizadas quando não há alterações no esquema ou há alterações no esquema não significativas.
A recuperação automática do cliente não pode ocorrer quando seu aplicativo faz alterações significativas no esquema. Uma alteração significativa é uma alteração que você pode fazer no esquema do lado do servidor que requer uma ação adicional com a qual lidar. Nesse cenário, a recuperação do cliente volta para um fallback de redefinição do cliente com erro manual.
Para obter informações sobre alterações de esquema significativas e não significativas, consulte Referência rápida de alterações significativas e não significativas na documentação do Atlas App Services .
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.
Especificar uma estratégia de reinício do cliente
Você pode especificar uma estratégia de reinício do cliente em seu SyncConfiguration.syncClientResetStrategy propriedade ao configurar um Realm sincronizado.
// Specify your client reset strategy in the SyncConfiguration // If you don't specify, defaults to RecoverOrDiscardUnsyncedChangesStrategy val config = SyncConfiguration.Builder(user, setOf(Toad::class)) .initialSubscriptions { realm -> add(realm.query<Toad>(), "subscription name") } .syncClientResetStrategy(clientResetStrategy) // Set your client reset strategy .build()
As seções a seguir descrevem como usar essas estratégias de redefinição do cliente.
Recuperar ou descartar alterações não sincronizadas
A estratégia de recuperar ou descartar alterações não sincronizadas tenta recuperar automaticamente todas as alterações locais não sincronizadas durante uma reinício do cliente. Para recuperar alterações não sincronizadas, a Recuperação de Cliente deve estar habilitada em seu App Services App (habilitada por padrão).
Se o processo de recuperação automática falhar, ele voltará para uma estratégia de descarte de alterações não sincronizadas. Se esse processo falhar, ele voltará para uma estratégia de reinício manual.
Essa estratégia fornece o processo de recuperação mais robusto. É o comportamento de reinício do cliente padrão se você não especificar uma estratégia de reinício do cliente.
Importante
Não use a estratégia de recuperar ou descartar alterações não sincronizadas se seu aplicativo não puder perder nenhum dado local que ainda não tenha sido sincronizado com o backend.
Para personalizar o uso da estratégia de recuperar ou descartar alterações não sincronizadas, defina uma classe que implemente a interface RecoverOrDiscardUnsyncedChangesStrategy .
A interface fornece os seguintes métodos de chamada de resposta:
onBeforeReset: invocado antes do reinício do cliente. Fornece uma instância do Realm antes da redefinição. Você pode usar esse chamada de resposta de chamada para notificar o usuário antes que a reinício do cliente comece.
onAfterRecovery: invocado se e somente se o reinício automático for concluído com êxito. Fornece uma instância somente leitura anterior do domínio e uma instância mutável do domínio final. Você pode usar esse retorno de chamada para notificar o usuário de que a redefinição do cliente foi concluída.
onAfterDiscard: invocado somente se o reinício do cliente automático falhar e a estratégia local de descarte for bem-sucedida. Se a estratégia de descarte falhar, este retorno de chamada não será invocado. Fornece uma instância somente leitura anterior do domínio e uma instância mutável do domínio final. Você pode usar esse retorno de chamada para notificar o usuário de que a redefinição foi concluída.
onManualResetFallback: invocado somente se a recuperação automática e a estratégia de descarte tiverem falhado. Descarta as alterações locais e permite criar um backup do domínio local. Implemente esse retorno de chamada para lidar com a falha de redefinição, conforme explicado na seção Recuo de recuperação manual.
O exemplo a seguir mostra o RecoverOrDiscardUnsyncedChangesStrategy
e cada uma de suas chamadas de resposta:
val clientResetStrategy = object : RecoverOrDiscardUnsyncedChangesStrategy { override fun onBeforeReset(realm: TypedRealm) { Log.i("Client reset: attempting to automatically recover unsynced changes") } // Executed before the client reset begins. // Can be used to notify the user that a reset will happen. override fun onAfterRecovery(before: TypedRealm, after: MutableRealm) { Log.i("Client reset: successfully recovered all unsynced changes") } // Executed if and only if the automatic recovery has succeeded. override fun onAfterDiscard(before: TypedRealm, after: MutableRealm) { Log.i("Client reset: recovery unsuccessful, attempting to manually recover any changes") // ... Try to manually recover any unsynced data manuallyRecoverUnsyncedData(before, after) } // Executed if the automatic recovery has failed, // but the discard unsynced changes fallback has completed successfully. override fun onManualResetFallback( session: SyncSession, exception: ClientResetRequiredException ) { Log.i("Client reset: manual reset required") // ... Handle the reset manually here } // Automatic reset failed. }
Recuperar alterações não sincronizadas
A estratégia de recuperar alterações locais não sincronizadas tenta recuperar automaticamente todas as alterações locais não sincronizadas durante uma redefinição do cliente. Para recuperar alterações não sincronizadas, a Recuperação de Cliente deve estar habilitada em seu App Services App (habilitada por padrão).
No entanto, ao contrário da estratégia de recuperar e descartar alterações não sincronizadas, ela não volta a descartar alterações locais se a recuperação automática falhar. Em vez disso, ele volta para recuperar manualmente as alterações. Você pode escolher essa estratégia de reinício do cliente se seu aplicativo não puder perder dados não sincronizados.
Para usar a estratégia de recuperar alterações não sincronizadas, defina um manipulador que implemente a interface RecoverUnsyncedChangesStrategy .
A interface fornece os seguintes métodos de chamada de resposta:
onBeforeReset: invocado antes do reinício do cliente. Fornece uma instância do Realm antes da redefinição. Você pode usar esse chamada de resposta de chamada para notificar o usuário antes que a reinício do cliente comece.
onAfterReset: invocado se e somente se o reinício automático for concluído com sucesso. Fornece uma instância somente leitura anterior do Realm e uma instância mutável do Realm final . Você pode usar esse chamada de resposta de chamada para notificar o usuário de que a reinício do cliente foi concluída.
onManualResetFallback: invocado somente se a recuperação automática tiver falhado. Descarta as alterações locais e permite criar um backup do Realm local . Implemente esse chamada de resposta de chamada para lidar com a falha de redefinição, conforme explicado na seção Recuo de recuperação manual.
O exemplo a seguir mostra o RecoverUnsyncedChangesStrategy
e cada uma de suas chamadas de resposta:
val clientResetStrategy = object : RecoverUnsyncedChangesStrategy { override fun onBeforeReset(realm: TypedRealm) { Log.i("Client reset: attempting to automatically recover unsynced changes") } // Executed before the client reset begins. // Can be used to notify the user that a reset will happen. override fun onAfterReset(before: TypedRealm, after: MutableRealm) { Log.i("Client reset: successfully recovered all unsynced changes") } // Executed after the client reset is complete. // Can be used to notify the user that the reset is done. override fun onManualResetFallback( session: SyncSession, exception: ClientResetRequiredException ) { Log.i("Client reset: manual reset required") // ... Handle the reset manually here } // Automatic reset failed. }
Descartar alterações não sincronizadas
A estratégia de descartar alterações não sincronizadas exclui permanentemente todas as alterações locais não sincronizadas feitas desde a última sincronização bem-sucedida. Essa estratégia restaura seu Arquivo de Realm local para um estado sincronizável sem fechar o Realm e, ao mesmo tempo, manter as notificações funcionando perfeitamente. Se esse processo falhar, ele voltará para uma estratégia de reinício manual.
Essa é a estratégia recomendada para lidar com qualquer recuperação manual de dados.
Você pode escolher essa estratégia 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.
Importante
Não use a estratégia de descartar alterações não sincronizadas se seu aplicativo não puder perder nenhum dado local que ainda não tenha sido sincronizado com o backend.
Para usar a estratégia de descartar alterações não sincronizadas, defina um manipulador que implemente a interface DiscardUnsyncedChangesStrategy .
A interface fornece os seguintes métodos de chamada de resposta:
onBeforeReset: invocado antes do reinício do cliente. Fornece uma instância do Realm antes da redefinição. Você pode usar esse chamada de resposta de chamada para notificar o usuário antes que a reinício do cliente comece.
onAfterReset: invocado se e somente se a redefinição for concluída. Fornece uma instância somente leitura anterior do domínio e uma instância mutável do domínio final. Você pode usar esse retorno de chamada para notificar o usuário de que a redefinição foi concluída.
onManualResetFallback: invocado somente se a recuperação automática e a estratégia de descarte tiverem falhado. Descarta as alterações locais e permite criar um backup do domínio local. Implemente esse retorno de chamada para lidar com a falha de redefinição, conforme explicado na seção Recuo de recuperação manual.
O exemplo a seguir mostra o DiscardUnsyncedChangesStrategy
e cada uma de suas chamadas de resposta:
val clientResetStrategy = object : DiscardUnsyncedChangesStrategy { override fun onBeforeReset(realm: TypedRealm) { Log.i("Client reset: attempting to discard any unsynced changes") } // Executed before the client reset begins. // Can be used to notify the user that a reset will happen. override fun onAfterReset(before: TypedRealm, after: MutableRealm) { Log.i("Client reset: attempting to manually recover any unsynced changes") // ...Try to manually recover any unsynced data manuallyRecoverUnsyncedData(before, after) } // Executed after the client reset is complete. // Can be used to notify the user that the reset is done. override fun onManualResetFallback( session: SyncSession, exception: ClientResetRequiredException ) { Log.i("Client reset: manual reset required") // ... Handle the reset manually here } // Automatic reset failed. override fun onError( session: SyncSession, exception: ClientResetRequiredException ) { // No-op } // Deprecated. onManualResetFallback() used instead. }
fallback de recuperação manual
Se a redefinição do cliente não puder ser concluída automaticamente, como quando há alterações no esquema de quebra, o processo de redefinição do cliente passará para um manipulador de erros manual.
Isso pode ocorrer em qualquer uma das estratégias de reinício automático do cliente:
Recuperar alterações não sincronizadas
Recuperar ou descartar alterações não sincronizadas
Descartar alterações não sincronizadas
Você deve fornecer uma implementação manual de redefinição do cliente na chamada de resposta onManualResetFallback
do manipulador de redefinição do cliente para essas estratégias.
O fallback de redefinição manual descarta as alterações locais e permite que você crie um backup do Realm local usando o método ClientResetRequiredException.executeClientReset .
override fun onManualResetFallback( session: SyncSession, exception: ClientResetRequiredException ) { Log.i("Client reset: manual reset required") // You *MUST* close any open Realm instance closeAllRealmInstances(); // `executeClientReset()` creates a backup exception.executeClientReset(); // (Optional) Send backup for analysis handleBackup(recoveryFilePath); // ... Restore the App state by reopening the realm // or restarting the app }
Recuperar manualmente alterações não sincronizadas
Use a estratégia de recuperação manual de alterações não sincronizadas para os casos pouco frequentes em que você precisa personalizar o processo de recuperação de dados. Recomendamos usar a estratégia Descartar alterações não sincronizadas , quando possível, para lidar com a recuperação manual de dados. Você só deve escolher a estratégia de recuperação manual de alterações não sincronizadas se a lógica de recuperação automática não for adequada para sua aplicação e você não puder descartar dados locais não sincronizados.
Para usar a estratégia de recuperação manual, defina seu próprio manipulador de redefinição de cliente usando a interface ManuallyRecoverUnsyncedChangesStrategy .
Antes de usar este método, você deve fechar todas as instâncias do Realm que está redefinindo. Todas as gravações no Arquivo de Realm feitas após a chamada de resposta de recuperação manual e antes do reinício do cliente sendo executada não serão sincronizadas. Também recomendamos que você crie uma cópia de segurança do arquivo e relate a exceção.
Inicie um reinício do cliente utilizando ClientResetRequiredException.executeClientReset()
.
Se a redefinição do cliente não for executada manualmente, ela será executada automaticamente na próxima vez que todas as instâncias do realm forem fechadas e reabertas (normalmente quando o aplicativo é reiniciado).
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.