Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Recuperação de dados de reinício do cliente - Node.js SDK

Nesta página

  • Rastrear alterações por estratégia de objeto
  • Exemplo
  • Incluir a hora da última atualização em seu esquema
  • Configurar o Realm para usar o reinício do cliente manual
  • Sincronização de rastreamento em Realm separado
  • Criar chamada de resposta para lidar com o reinício do cliente
  • Estratégias alternativas

Esta página explica como recuperar manualmente dados do Realm não sincronizados após um reinício do cliente usando o modo de reinício do cliente de Recuperação Manual.

A recuperação manual requer quantidades significativas de código, concessões de esquema e lógica personalizada de resolução de conflitos. Você só deve executar uma recuperação manual de dados de Realm não sincronizados se não puder perder dados não sincronizados e os outros métodos de reinício do cliente automática não atenderem ao seu caso de uso.

Para obter mais informações sobre os outros modos de reinício do cliente disponíveis, consulte Redefinir um Realm do Cliente.

As especificidades da recuperação manual dependem muito do seu aplicativo e do seu esquema. No entanto, existem algumas técnicas que podem ajudar nas recuperações manuais. A seção Estratégia de rastreamento de objeto demonstra um método de recuperar alterações não sincronizadas durante uma redefinição do cliente.

Aviso

Evite fazer alterações significativas no esquema na produção

Não espere recuperar todos os dados não sincronizados após uma alteração significativa no esquema. A melhor maneira de preservar os dados do usuário é nunca fazer uma alteração significativa no esquema.

Importante

As alterações de esquema de ruptura exigem uma atualização de esquema de aplicativo

Após uma alteração significativa no esquema:

  • Todos os clientes devem fazer um reinício do cliente.

  • Você deve atualizar os modelos de cliente afetados pela alteração do esquema de quebra.

A estratégia de recuperação de dados de reinício do cliente de objeto permite recuperar dados já gravados no Arquivo de Realm do cliente, mas ainda não sincronizados com o backend.

Nesta estratégia, você adiciona um "horário da última atualização" a cada modelo de objeto para acompanhar quando cada objeto foi alterado pela última vez. Observaremos para determinar quando o Realm carregou pela última vez seu estado para o back-end.

Quando o backend invoca um reinício do cliente, localize objetos que foram excluídos, criados ou atualizados desde a última sincronização com o backend. Em seguida, copie esses dados do Realm de backup para o novo Realm.

As etapas a seguir demonstram a implementação do processo em um alto nível:

  1. Erro de reinício do cliente: sua aplicação recebe um código de erro de reinício do cliente do backend.

  2. Implementação da estratégia: o SDK chama a implementação da estratégia.

  3. Feche todas as instâncias do Realm: Feche todas as instâncias abertas do Realm que estão enfrentando o reinício do cliente. Se a arquitetura da sua aplicação dificultar isso (por exemplo, se a sua aplicação usar muitas Instância de Realm simultaneamente em ouvintes em toda a aplicação), pode ser mais fácil reiniciar a aplicação. Você pode fazer isso programaticamente ou por meio de uma solicitação direta ao usuário em uma caixa de diálogo.

  4. Mova o domínio para um arquivo de backup: Ligue para o Realm.App.Sync.initiateClientReset() método estático. Este método move a cópia atual do arquivo de domínio do cliente para um arquivo de backup.

  5. Abra uma nova instância do Realm: Abra uma nova instância do Realm usando sua configuração de sincronização típica. Se a sua aplicação usar vários Realms, você poderá identificar o Realm que está enfrentando um reinício do cliente a partir do nome do arquivo de backup.

  6. Baixar todos os dados do domínio do backend: Baixe todo o conjunto de dados no domínio antes de prosseguir. Este é o comportamento padrão do objeto SyncConfiguration .

  7. Open the Realm backup: Use o objeto error.config passado como argumento para a função de chamada de resposta SyncConfiguration.error .

  8. Migrar alterações não sincronizadas: Query o Realm de backup para obter dados a serem recuperados. Insira, exclua ou atualize dados no novo Realm adequadamente.

Este exemplo demonstra a implementação das alterações de rastreamento por objeto estratégia de recuperação de dados de reinício do cliente .

Observação

Limitações deste exemplo

  • Este exemplo é apenas para um aplicativo com um único realm contendo um único tipo de objeto de Realm. Para cada tipo de objeto adicional, você precisa adicionar outro ouvinte de sincronização, conforme descrito na seção Sincronização de faixas em Realm separados.

  • Este exemplo acompanha a última vez que cada objeto foi atualizado. Como resultado, a operação de recuperação substitui todo o objeto no novo Realm se algum campo foi atualizado após a última sincronização bem-sucedida do Realm de backup. Isso pode substituir campos atualizados por outros clientes por dados antigos desse cliente. Se o seu Objeto de Realm contiver vários campo contendo dados importantes, considere acompanhar a hora da última atualização de cada campo e recuperar cada campo individualmente.

Para obter mais informações sobre outras maneiras de executar um reinício do cliente manual com recuperação de dados, consulte a seção Estratégias Alternativas.

1

Adicione uma nova propriedade ao seu esquema de objetos de Realm para acompanhar a última vez que ela foi atualizada. Sempre que você criar ou atualizar um Objeto de Realm com o esquema, inclua um carimbo de data/hora com a hora de atualização.

Normalmente, não há como detectar quando um Objeto de Realm foi modificado pela última vez. Isso torna difícil determinar quais alterações foram sincronizadas com o backend. Ao adicionar um carimbo de data/hora lastUpdated aos seus modelo de objetos de Realm e atualizar esse carimbo de data/hora para a hora atual sempre que ocorre uma alteração, você pode acompanhar quando os objeto foram alterados.

const DogSchema = {
name: "Dog",
properties: {
name: "string",
age: "int?",
lastUpdated: "int",
},
};
2

Na SyncConfiguration do realm, defina o campo clientReset como modo manual e inclua uma função de retorno de chamada error . Você definirá a função de chamada de resposta de erro na seção Criar chamada de resposta para lidar com o reinício do cliente.

const config = {
schema: [DogSchema],
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
clientReset: {
mode: "manual",
},
error: handleSyncError, // callback function defined later
},
};
3

Apenas saber quando o objeto foi alterado não é suficiente para recuperar dados durante um reinício do cliente. Você também precisa saber quando o Realm concluiu pela última vez uma sincronização com sucesso. Esta implementação de exemplo usa um objeto em um Realm separado chamado LastSynced emparelhado com um ouvinte de alterações para registrar quando um Realm terminar a sincronização com êxito.

Defina seu Realm mais recente sincronizado para acompanhar a última vez em que seu domínio foi sincronizado.

const LastSyncedSchema = {
name: "LastSynced",
properties: {
realmTracked: "string",
timestamp: "int?",
},
primaryKey: "realmTracked",
};
const lastSyncedConfig = { schema: [LastSyncedSchema] };
const lastSyncedRealm = await Realm.open(lastSyncedConfig);
lastSyncedRealm.write(() => {
lastSyncedRealm.create("LastSynced", {
realmTracked: "Dog",
});
});

Registre um ouvinte de alterações para assinar as alterações na collection Dog. Atualize somente o objeto lastSynced se a sessão de sincronização estiver conectada e todas as alterações locais tiverem sido sincronizadas com o servidor.

// Listens for changes to the Dogs collection
realm.objects("Dog").addListener(async () => {
// only update LastSynced if sync session is connected
// and all local changes are synced
if (realm.syncSession.isConnected()) {
await realm.syncSession.uploadAllLocalChanges();
lastSyncedRealm.write(() => {
lastSyncedRealm.create("LastSynced", {
realmTracked: "Dog",
timestamp: Date.now(),
});
});
}
});
4

Agora que você registrou os tempos de atualização de todos os objetos do seu aplicativo, bem como a última vez que seu aplicativo concluiu uma sincronização, é hora de implementar o processo de recuperação manual. Este exemplo lida com duas operações de recuperação principais:

  • Restaurar inserções e atualizações não sincronizadas do Realm de backup

  • Excluir objetos do novo domínio que foram excluídos anteriormente do domínio de backup

Você pode acompanhar a implementação dessas operações nas amostras de código abaixo.

async function handleSyncError(_session, error) {
if (error.name === "ClientReset") {
const realmPath = realm.path; // realm.path will not be accessible after realm.close()
realm.close(); // you must close all realms before proceeding
// pass your realm app instance and realm path to initiateClientReset()
Realm.App.Sync.initiateClientReset(app, realmPath);
// Redownload the realm
realm = await Realm.open(config);
const oldRealm = await Realm.open(error.config);
const lastSyncedTime = lastSyncedRealm.objectForPrimaryKey(
"LastSynced",
"Dog"
).timestamp;
const unsyncedDogs = oldRealm
.objects("Dog")
.filtered(`lastUpdated > ${lastSyncedTime}`);
// add unsynced dogs to synced realm
realm.write(() => {
unsyncedDogs.forEach((dog) => {
realm.create("Dog", dog, "modified");
});
});
// delete dogs from synced realm that were deleted locally
const syncedDogs = realm
.objects("Dog")
.filtered(`lastUpdated <= ${lastSyncedTime}`);
realm.write(() => {
syncedDogs.forEach((dog) => {
if (!oldRealm.objectForPrimaryKey("Dog", dog._id)) {
realm.delete(dog);
}
});
});
// make sure everything syncs and close old realm
await realm.syncSession.uploadAllLocalChanges();
oldRealm.close();
} else {
console.log(`Received error ${error.message}`);
}
}

Possíveis implementações alternativas incluem:

  • Substitua todo o backend pelo estado do backup: sem "hora da última atualização" ou "hora da última sincronização", faça o upsert de todos os objeto do Realm de backup no novo Realm. Não há como recuperar exclusões não sincronizadas com essa abordagem. Essa abordagem substitui todos os dados gravados no backend por outros clientes desde a última sincronização. Recomendado para aplicação em que apenas um usuário grava em cada Realm.

  • Rastrear alterações por campo: em vez de rastrear uma "hora da última atualização" para cada objeto, acompanhe a "hora da última atualização" de cada campo. Atualize os campos individualmente usando essa lógica para evitar a substituição de gravações de campos de outros clientes por dados antigos. Recomendado para aplicativos com muitos campos por objeto onde os conflitos devem ser resolvidos no nível do campo.

  • Acompanhe as atualizações separadamente dos objetos: em vez de acompanhar uma "hora da última atualização" no esquema de cada objeto, crie outro modelo no seu esquema chamado Updates. Toda vez que qualquer campo em qualquer objeto (além Updates) for atualizado, registre a chave primária, o campo e a hora da atualização. Durante um reinício do cliente, "reescreva" todos os evento Update que ocorreram após o "último tempo sincronizado" usando o valor mais recente desse campo no Realm de backup. Essa abordagem deve replicar todas as alterações locais não sincronizadas no novo Realm sem substituir nenhum campo por dados obsoletos. No entanto, armazenar a collection de atualizações pode se tornar caro se sua aplicação for gravado com frequência. Recomendado para aplicativos em que adicionar campos "lastUpdated" a modelos de objetos não é desejável.

Voltar

Gerenciar erros de sincronização