Gerenciar erros de sincronização - SDK do Node.js
Nesta página
- Manipulador de erros de sincronização
- Adicionar um manipulador de erros de sincronização genérico
- Lidar com erros de gravação compensatórios
- Lidar com erros de reinício do cliente
- Modos de reinício do cliente
- reinício do cliente automático versus manual
- Redefinição do cliente com recuperação
- Modo Recuperar alterações não sincronizadas
- Recuperar ou descartar modo de alterações não sincronizadas
- fallback de reinício do cliente
- Modo de descartar alterações não sincronizadas
- Descartar alterações não sincronizadas após interromper as alterações do esquema
- Modo manual
- Recuperação manual de dados
- Tratamento de reinício do cliente de teste
Ao utilizar o Atlas Device Sync em seu aplicativo Realm , você pode encontrar uma nova classe de erros: erros de sincronização.
O Realm Node.js SDK pode ajudá-lo a detectar e lidar com erros de sincronização. Por exemplo, você pode escrever seu próprio manipulador de erros de sincronização para responder a erros específicos. Você também pode definir como seu aplicativo cliente lida com o reinício do cliente.
Manipulador de erros de sincronização
Você deve definir um manipulador de erros para aplicativos que usam o Atlas Device Sync. Um manipulador de erros genérico detectará e responderá a chamadas de API relacionadas à sincronização com falha para seu backend do Atlas.
Adicionar um manipulador de erros de sincronização genérico
Defina um manipulador de erro registrando uma função de chamada de resposta de chamada de erro como parte da SyncConfiguration.
const handleSyncError = async (session, error) => { // ... handle the error using session and error information. console.log(session); console.log(error); }; const config = { schema: [DogSchema], sync: { flexible: true, user: app.currentUser, onError: handleSyncError, }, }; // Open realm with config that contains error handler. const realm = await Realm.open(config);
const handleSyncError = ( session: Realm.App.Sync.Session, error: Realm.SyncError | Realm.ClientResetError ) => { // ... handle the error using session and error information. console.log(session); console.log(error); }; const config: Realm.Configuration = { schema: [DogSchema], sync: { flexible: true, user: app.currentUser!, onError: handleSyncError, }, }; // Open realm with config that contains error handler. const realm = await Realm.open(config);
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 .
Lidar com erros de gravação compensatórios
Talvez você queira que seu manipulador de erros de sincronização aborde especificamente os erros de escrita compensatórios de uma forma que faça sentido para o seu aplicativo. A classe CompensatingWriteError pode ajudá-lo a identificar e React a erros de escrita compensatórios em seu manipulador de erros personalizado.
const errorCallback = (session, error) => { // Check if error type matches CompensatingWriteError. if (error instanceof CompensatingWriteError) { // Handle the compensating write error as needed. console.debug({ name: error.name, code: error.code, message: error.message, atlasLogUrl: error.logUrl, }); const compensatingWrites = error.writes.sort((a, b) => a.primaryKey.toString().localeCompare(b.primaryKey.toString()) ); console.debug(compensatingWrites); } }; const app = new Realm.App({ id: APP_ID, }); const credentials = Credentials.anonymous(); await app.logIn(credentials); const realm = await Realm.open({ schema: [Person, Turtle], sync: { flexible: true, user: app.currentUser, onError: errorCallback, }, });
const errorCallback: ErrorCallback = (session, error) => { // Check if error type matches CompensatingWriteError. if (error instanceof CompensatingWriteError) { // Handle the compensating write error as needed. console.debug({ name: error.name, code: error.code, message: error.message, atlasLogUrl: error.logUrl, }); const compensatingWrites = error.writes.sort((a, b) => (a.primaryKey as BSON.ObjectId) .toString() .localeCompare((b.primaryKey as BSON.ObjectId).toString()) ); console.debug(compensatingWrites); } }; const app = new Realm.App({ id: APP_ID, }); const credentials = Credentials.anonymous(); await app.logIn(credentials); const realm = await Realm.open({ schema: [Person, Turtle], sync: { flexible: true, user: app.currentUser!, onError: errorCallback, }, });
Lidar com erros de reinício do cliente
Um reinício do cliente é uma situação em que um Realm não consegue sincronizar dados com o backend do Atlas App Services. Clientes neste estado podem continuar executando e salvando dados localmente, mas não podem enviar ou receber conjuntos de alterações de sincronização até fazerem um reinício do cliente.
Para saber mais sobre as causas e os modos de lidar com as redefinições do cliente, consulte Redefinições do cliente do Device Sync na documentação do Atlas App Services .
Modos de reinício do cliente
Você pode especificar qual reinício do cliente seu aplicativo deve usar para restaurar o Realm para um estado sincronizável:
modo Recuperar alterações não sincronizadas: Ao escolher este modo, o cliente tenta recuperar as alterações não sincronizadas. Escolha este modo quando não quiser descartar alterações não sincronizadas.
modo de recuperação ou descarte de alterações não sincronizadas : 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.
modo de descartar alterações não sincronizadas : restaura o Realm para um estado sincronizável descartando as alterações feitas desde a última sincronização.
Modo de recuperação manual: baixa uma nova cópia do domínio e move o domínio não sincronizável para um backup. Migre dados não sincronizados da cópia de backup do domínio para a nova cópia sincronizável.
reinício do cliente automático versus manual
Os SDKs do Realm oferecem modos de reinício do cliente que lidam automaticamente com a maioria dos erros de reinício do cliente.
Os modos automáticos de redefinição do cliente restauram seu arquivo de domínio local para um estado sincronizável sem fechar o domínio ou perder notificações. Os seguintes modos de reinício do cliente são compatíveis com o reinício do cliente automático:
Recuperar modo de alterações não sincronizadas
Recuperar ou descartar o modo de alterações não sincronizadas
Descartar modo de alterações não sincronizadas
As diferenças entre esses modos são baseadas em como eles lidam com alterações no dispositivo que ainda não foram sincronizadas com o backend. Somente o modo de recuperação manual não executa um reinício automático do cliente.
Escolha o modo recuperar alterações não sincronizadas para lidar com a maioria dos cenários de redefinição de cliente automaticamente. Isso tenta recuperar alterações não sincronizadas quando ocorre uma redefinição de cliente.
Se o seu aplicativo exigir uma lógica específica de redefinição de cliente que não possa ser tratada automaticamente, convém ou precise adicionar um manipulador manual de redefinição de cliente ao modo de redefinição automática de cliente.
Redefinição do cliente com recuperação
Novidades na versão 10.23.0.
A recuperação do cliente é um recurso habilitado por padrão quando você configura o Realm Mobile Sync. Quando a Recuperação de Cliente está habilitada, o Realm gerencia automaticamente o processo de redefinição do cliente na maioria dos casos. O cliente pode recuperar alterações não sincronizadas quando não há alterações no esquema ou alterações no esquema não significativas.
Para usar a Recuperação de Cliente, configure seu domínio com um dos seguintes modos de redefinição de cliente:
Recuperar modo de alterações não sincronizadas
Recuperar ou descartar alterações não sincronizadas
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.
Para obter mais informações sobre como configurar a Recuperação de Cliente, consulte Recuperação de Cliente na documentação do Atlas App Services .
A Recuperação de Cliente não pode ser bem-sucedida quando seu aplicativo faz alterações de esquema de quebra. 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 redefiniçã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 .
Modo Recuperar alterações não sincronizadas
Quando você escolhe o modo de recuperar alterações não sincronizadas , o cliente tenta recuperar as alterações não sincronizadas com a Recuperação do Cliente. Escolha este modo se não quiser descartar alterações não sincronizadas.
Para gerenciar as redefinições do cliente com o modo de recuperação de alterações não sincronizadas , passe um ClientResetConfig para o campo clientReset
da SyncConfiguration. Inclua estas propriedades no ClientResetConfiguration
:
mode
: Defina como"recoverUnsyncedChanges"
.onBefore
: Opcional. Função de retorno de chamada invocada antes do SDK executar esse modo, quando o SDK recebe um erro de redefinição do cliente do backend. Fornece uma cópia do domínio.onAfter
: Opcional. Função de chamada de resposta invocada após o SDK executar com sucesso este modo. Fornece instâncias do Realm antes e depois do reinício do cliente.onFallback
: Opcional. Função de retorno de chamada que o SDK invoca somente se a recuperação automática falhar. Para obter mais informações, consulte a seção Queda de redefinição manual do cliente.
O exemplo a seguir implementa o modo de recuperação de alterações não sincronizadas :
const config = { schema: [DogSchema], sync: { user: app.currentUser, 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 }, }, }, };
Recuperar ou descartar modo de alterações não sincronizadas
No modo de recuperar ou descartar alterações não sincronizadas, 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 descartará as alterações não sincronizadas, mas continuará executando automaticamente o reinício do cliente. Escolha esse modo se quiser habilitar a recuperação automática do cliente para voltar a descartar as alterações não sincronizadas.
Não use o modo recuperar ou descartar alterações não sincronizadas se o aplicativo não puder perder dados locais que ainda não foram sincronizados com o backend.
Para lidar com as redefinições do cliente com o modo recuperar ou descartar alterações não sincronizadas , passe um ClientResetConfig para o campo clientReset
do SyncConfiguration. Inclua estas propriedades no ClientResetConfiguration
:
mode
: Defina como"recoverOrDiscardUnsyncedChanges"
.onBefore
: Opcional. Função de retorno de chamada invocada antes do SDK executar esse modo, quando o SDK recebe um erro de redefinição do cliente do backend. Fornece uma cópia do domínio.onAfter
: Opcional. Função de chamada de resposta invocada após o SDK executar com sucesso este modo. Fornece instâncias do Realm antes e depois do reinício do cliente.onFallback
: Opcional. Função de retorno de chamada que o SDK invoca somente se a recuperação automática e o descarte das alterações falharem. Para obter mais informações, consulte a seção Queda de redefinição manual do cliente.
O exemplo a seguir implementa o modo de recuperação de alterações não sincronizadas :
const config = { schema: [DogSchema], sync: { user: app.currentUser, 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 }, }, }, };
fallback de reinício do cliente
Se o reinício do cliente com recuperação não puder ser concluído automaticamente, como quando há alterações significativas no esquema, o processo de reinício do cliente passará para um manipulador de erros manual. Isso pode ocorrer no reinício do cliente com modos de recuperação, recuperar alterações não sincronizadas e recuperar ou descartar alterações não sincronizadas.
Você deve fornecer uma implementação manual de reinício do cliente na chamada de resposta SyncConfiguration.onFallback()
. onFallback()
recebe dois argumentos:
session
: objeto de sessão que representa o estado da sessão do Device Sync .path
: string com o caminho para o Arquivo de Realm atual.
O exemplo a seguir demonstra como você pode lidar manualmente com esse caso de erro descartando todas as alterações não sincronizadas:
// Must define `realm` at higher scope than `config` so it's accessible // from the `onFallback` callback let realm; const config = { schema: [DogSchema], sync: { user: app.currentUser, 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 } }, }, }, }; realm = await Realm.open(config);
Modo de descartar alterações não sincronizadas
Novidade na versão 10.11.0.
Alterado na versão 10,23,0: Modo renomeado de "discardLocal" para "discardUnsyncedChanges". Ambos funcionam atualmente, mas em uma versão futura, "discardLocal" será removido. Chamadas de resposta "clientResetBefore" e "clientResetAfter" renomeadas para "onBefore" e "onAfter", respectivamente.
O modo Descartar alterações não sincronizadas exclui permanentemente todas as alterações locais não sincronizadas feitas desde a última sincronização bem-sucedida. Você pode usar esse modo quando seu aplicativo exigir uma lógica de recuperação do cliente que não seja consistente com a Recuperação automática do cliente ou quando 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 lidar com as redefinições do cliente com o modo de descartar alterações não sincronizadas , passe um ClientResetConfig para o campo clientReset
do SyncConfiguration. Inclua estas propriedades no ClientResetConfiguration
:
mode
: Defina como"discardUnsyncedChanges"
.onBefore
: Opcional. Função de retorno de chamada invocada antes do SDK executar esse modo, quando o SDK recebe um erro de redefinição do cliente do backend. Fornece uma cópia do domínio.onAfter
: Opcional. Função de chamada de resposta invocada após o SDK executar com sucesso este modo. Fornece instâncias do Realm antes e depois do reinício do cliente.
O exemplo a seguir implementa o modo de descarte de alterações não sincronizadas:
const config = { schema: [DogSchema], sync: { user: app.currentUser, 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); }, }, }, };
Descartar alterações não sincronizadas após interromper as alterações do esquema
Se a sua aplicação sofrer uma alteração significativa no esquema, o modo de descarte de alterações não sincronizadas não poderá lidar com o reinício do cliente resultante automaticamente. Em vez disso, você deve fornecer uma implementação manual de reinício do cliente na chamada de resposta SyncConfiguration error()
. O exemplo a seguir demonstra como você pode lidar manualmente com esse caso de erro descartando todas as alterações não sincronizadas:
// 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 config = { schema: [DogSchema], sync: { user: app.currentUser, 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 }, };
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 seção Recuperar ou descartar alterações não sincronizadas .
Modo manual
Alterado na versão 10.23.0: adição de chamada de resposta onManual
No modo manual , você define seu próprio manipulador de redefinição do cliente. Talvez você queira usar um manipulador de redefinição manual do cliente se a lógica de recuperação automática não funcionar para seu aplicativo e você não puder descartar dados locais não sincronizados.
Para gerenciar as redefinições do cliente com o modo manual, passe um ClientResetConfig para o campo clientReset
do SyncConfiguration. Inclua estas propriedades no ClientResetConfiguration
:
mode
: Defina como"manual"
.onManual
: Opcional. Função de retorno de chamada invocada quando ocorre a redefinição do cliente. Fornece informações sobre a sessão de sincronização e o caminho para o realm atual. Se você não definir o manipulador de errosonManual
, o reinício do cliente voltará para o manipulador de erros de sincronização geral.
const config = { schema: [DogSchema], sync: { user: app.currentUser, flexible: true, clientReset: { mode: "manual", onManual: (session, path) => { // handle manual client reset here }, }, }, };
Recuperação manual de dados
Para recuperar dados de um reinício do cliente manual, são necessárias quantidades significativas de código, concessões de esquema e lógica personalizada de resolução de conflitos. Se você precisar implementar sua própria lógica personalizada de reinício do cliente, consulte o Guia Avançado para Recuperação manual de dados de reinício do cliente.
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.