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

Gerenciar assinaturas de sincronização - Flutter SDK

Nesta página

  • Pré-requisitos
  • Alinhe assinaturas com aplicativo de backend
  • Inscrever-se para receber queries
  • Inscrever-se em uma query
  • Aguarde uma assinatura de query para sincronizar
  • Cancelar assinatura de uma query
  • Gerenciar assinaturas manualmente
  • Obter assinaturas
  • Adicionar uma query ao conjunto de assinaturas
  • Atualizar assinaturas com uma nova query
  • Remover subscrições
  • Aguarde as alterações na assinatura para sincronizar
  • Estado da assinatura
  • Requisitos e limitações do Flexible Sync RQL
  • Requisitos de inscrição de campos de query indexados
  • Operadores de consulta não suportados na sincronização flexível
  • Listar queries
  • Objetos incorporados ou vinculados
  • Limite de tamanho da query
  • Considerações de desempenho
  • Eficiência da API
  • Atualizações de grupo para melhorar o desempenho

O Atlas Device Sync com Flexible Sync usa assinaturas e permissões para determinar quais dados sincronizar entre o Atlas e seu aplicativo.

Você pode adicionar, atualizar e remover assinaturas de query para determinar quais dados são sincronizados com o dispositivo cliente.

Observação

Pré-requisitos do Flexible Sync

A ativação da Flexible Sync em seu aplicativo requer um cluster de Atlas não fragmentado que esteja executando o MongoDB 5.0 ou superior

Para usar a Flexible Sync em um aplicativo Flutter:

  1. Configurar o Flexible Sync no backend do Atlas App Services

  2. Inicialize o cliente do aplicativo

  3. Autenticar um usuário no cliente

  4. Abra o domínio sincronizado no cliente

Suas queries de assinatura do lado do cliente devem estar alinhadas com a configuração do Device Sync em seu aplicativo de serviços de aplicativo de backend.

Suas query de assinatura podem:

Novidade na versão v1,6,0.

O Flutter v1.6.0 adiciona API experimentais que se inscrevem e cancelam a assinatura dos resultados de uma query. Essas API resumem os detalhes de adicionar e remover assinaturas manualmente.

Para todas as assinaturas, você precisa de um usuário autenticado e de um domínio sincronizado.

Se você precisar de mais controle sobre as assinaturas por motivos de otimização de desempenho ou lógica de negócios, poderá gerenciar manualmente o conjunto de assinaturas usando a API subscriptions . Consulte a seção Considerações sobre desempenho nesta página para obter mais informações.

Você pode assinar o RealmResults de uma query usando o subscribe() método. Quando chamado, o SDK cria a nova assinatura e a adiciona ao MutableSubscriptionSet, semelhante à criação manual de assinaturas.

Opcionalmente, você pode passar um nome de assinatura exclusivo para a query. Se você adicionar uma assinatura com o mesmo nome de uma assinatura existente, o SDK substituirá a assinatura existente.

Se você não passar um nome de assinatura, o nome será definido como null e o identificador de assinatura será baseado na string de query. Isto significa que toda vez que sua string de query muda, o subscribe() cria uma nova assinatura.

Para assinar uma query, passe os seguintes argumentos para subscribe():

  • RealmResults query: Obrigatório. Um objeto RealmResults que você pode criar usando a Realm Query Language.

  • String name: Opcional. Nome da assinatura que você pode consultar.

  • bool update: Opcional. Quando verdadeiro, adicionar uma assinatura com um nome existente substitui a query existente pela nova query. Quando falso, o SDK lança uma exceção para assinaturas duplicadas. Use apenas com assinaturas nomeadas.

No exemplo a seguir, assinamos duas novas query nomeadas.

final boatQuery = realm.all<Boat>();
final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final boatSubscription = await boatQuery.subscribe(name: "boats");
final planeSubscription =
await bigPlaneQuery.subscribe(name: "big-planes");

Dica

Especificar um nome de assinatura

Recomendamos que você sempre especifique um nome para a assinatura, especialmente se seu aplicativo usar várias assinaturas. Isso torna mais fácil encontrar e gerenciar suas assinaturas.

Quando você assina os resultados de uma query, os resultados não contêm objetos até que os dados sincronizados sejam baixados. Quando for necessário aguardar o término do download dos objetos sincronizados, configure o waitForSyncMode opção.

Este exemplo utiliza a opção firstTime , que é o comportamento padrão. Uma assinatura com comportamento firstTime somente aguarda a sincronização terminar quando uma assinatura é criada pela primeira vez.

final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "firstTimeSync",
waitForSyncMode: WaitForSyncMode.firstTime,
);

As outras opções waitForSyncMode suportadas são:

  • always: Aguarde o download dos objetos correspondentes toda vez que seu aplicativo for iniciado. O aplicativo deve ter uma conexão com a Internet em cada lançamento.

  • never: Nunca espere para baixar objetos correspondentes. O aplicativo precisa de uma conexão com a Internet para que o usuário se autentique na primeira vez que o aplicativo for iniciado, mas pode ser aberto offline nas execuções subsequentes usando credenciais em cache.

Opcionalmente, você pode especificar um Token de cancelamento para limitar quanto tempo o download de sincronização é executado:

final bigPlaneQuery = realm.query<Plane>("numSeats > 200");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "alwaysWaitSync",
waitForSyncMode: WaitForSyncMode.always,
cancellationToken: TimeoutCancellationToken(Duration(seconds: 5)),
);

As assinaturas persistem entre as sessões de usuário, a menos que você cancele a assinatura delas. Você pode cancelar a assinatura dos resultados de uma query usando cancelar a assinatura ().

Isso remove a assinatura da lista de assinaturas ativas, semelhante à remoção manual de uma assinatura. Observe que a lista de resultados ainda pode conter objetos depois de ligar unsubscribe() se houver outra assinatura que contenha objetos sobrepostos.

Quando você chama unsubscribe() em uma query, o SDK remove todas as assinaturas com queries que correspondem exatamente à que você chama unsubscribe() . Esse método retorna antes que o objeto correspondente à assinatura removida seja excluído do Realm. A sincronização continua em segundo plano com base no novo conjunto de assinaturas.

planeQuery.unsubscribe();
trainQuery.unsubscribe();

Ao configurar o Flexible Sync no backend, você especifica quais campos seu aplicativo cliente pode executar uma query. No aplicativo do cliente, use o realm.Subscriptions propriedade para gerenciar um conjunto de assinaturas para queries específicas em campos consultáveis.

Você pode fazer o seguinte com suas assinaturas:

  • Obter uma lista de todas as assinaturas

  • Adicionar subscrições

  • Verificar estado da assinatura

  • Atualizar uma assinatura com uma nova query

  • Remover subscrições

Quando os dados correspondem à assinatura e o usuário autenticado tem as permissões apropriadas, o Device Sync sincroniza os dados de backend com o aplicativo cliente.

Os conjuntos de assinaturas persistem entre sessões, mesmo que você não inclua mais a assinatura em seu código. As informações de assinatura são armazenadas no arquivo de reconhecimento de data center do Realm sincronizado. Você deve remover explicitamente uma assinatura para que pare de tentar sincronizar os dados correspondentes.

Você pode especificar um nome de string para sua assinatura. Se você não der um nome à sua assinatura, o nome será definido como null.

Quando você cria uma assinatura, o Realm procura dados correspondentes a uma query em um Tipo de objeto de Realm específico. Em suas assinaturas do Flexible Sync, você pode ter assinaturas em vários Tipo de objeto de Realm diferentes ou várias query no mesmo Tipo de objeto de Realm.

Ao usar o Flexible Sync, você pode acessar um conjunto de assinaturas , uma collection de assinaturas, por meio da Realm.subscriptions propriedade .

Você pode usar esse conjunto de assinaturas para adicionar query a essa lista de assinaturas e atualizar assinaturas existentes, conforme mostrado nos exemplos abaixo.

final subscriptions = realm.subscriptions;

Você deve realizar todas as mutações no conjunto de assinaturas dentro de um bloco de atualização. Para criar um bloco de atualização, chame SubscriptionSet.update().

A função de retorno de chamada do bloco de atualização inclui um MutableSubscriptionSet() objeto como argumento. Você pode modificar seu método no SubscriptionSet para adicionar uma query à assinatura.

Importante

Flexible Sync não é compatível com todos os operadores disponíveis no RQL. Consulte LimitaçõesFlexible Sync RQL de sincronização para obter detalhes.

O método MutableSubscriptionSet.add() utiliza três argumentos:

  • RealmResults query: Obrigatório. Um objeto RealmResults que você pode criar usando a query RealmQL.

  • String name: Opcional. Nome da assinatura que você pode consultar.

  • bool update: Opcional. Quando verdadeiro, adicionar uma assinatura com um nome existente substitui a query existente pela nova query. Use apenas com assinaturas nomeadas.

Observação

assinaturas duplicadas

Se você adicionar uma assinatura duplicada sem nome com a mesma query, o Realm a removerá automaticamente; adicionar uma assinatura nomeada idêntica é um não operacional . Portanto, em ambos os casos, as assinaturas duplicadas são ignoradas.

Você pode adicionar uma única query ou várias queries em lote em um bloco SubscriptionSet.update . Executar atualizações de query é uma operação cara no servidor. É altamente recomendável projetar seu aplicativo para minimizar as atualizações de assinatura. Você pode fazer isso criando todas as assinaturas em um único bloco de atualização na primeira vez que o usuário iniciar o aplicativo e agrupando em lote quaisquer alterações de acompanhamento no conjunto de assinaturas.

No exemplo abaixo, assinamos duas query.

final planeQuery = realm.all<Plane>();
final longTrainQuery = realm.query<Train>("numCars >= 5");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(planeQuery, name: "planes");
mutableSubscriptions.add(longTrainQuery,
name: 'long-trains', update: true);
});
await realm.subscriptions.waitForSynchronization();

Você pode atualizar uma assinatura nomeada com uma nova query. Para atualizar a query de uma assinatura, abra um bloco de atualização com SubscriptionSet.update(). Na função de retorno de chamada do bloco de atualização, passe os seguintes argumentos para MutableSubscriptionSet.add() :

  • A nova query

  • O nome da assinatura que você deseja atualizar

  • update: true

Você não pode atualizar uma assinatura sem nome. Como alternativa, você pode excluir a assinatura sem nome e criar uma nova assinatura com a query desejada.

No exemplo a seguir, trechos longos são redefinidos como quaisquer trechos que tenham mais de 10 vagões.

final longerTrainQuery = realm.query<Train>("numCars > 10");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(longerTrainQuery,
name: 'long-trains', update: true);
});

Para remover assinaturas do conjunto de assinaturas, você pode:

  • Remover uma única assinatura com a query fornecida

  • Remover uma única assinatura com o nome fornecido

  • Remover uma única assinatura com a referência de assinatura

  • Remover todas as assinaturas para um Tipo de objeto de Realm

  • Remover todas as assinaturas

Quando você remove uma query de assinatura, o servidor também remove os dados sincronizados do dispositivo cliente.

Dentro de um bloco de atualização, você pode remover uma assinatura específica por query. Abra um bloco de atualização com SubscriptionSet.update(). Passe o Subscription para MutableSubscriptionSet.removeByQuery().

No exemplo a seguir, a assinatura de todos os objetos Plane é removida.

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByQuery(realm.all<Plane>());
});

Dentro de um bloco de atualização, você pode remover uma assinatura específica por nome. Passe o nome para MutableSubscriptionSet.removeByName()

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByName('long-trains');
});

Você pode remover uma assinatura se tiver uma referência à sua Assinatura evento. Dentro de um bloco de atualização de assinatura, passe a Subscription referência para MutableSubscriptionSet.remove().

final sub = realm.subscriptions[0];
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.remove(sub);
});

Você pode remover todas as assinaturas de um determinado tipo de objeto do Realm. Dentro de um bloco de atualização de assinatura, ligue para MutableSubscriptionSet.removeByType().

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByType<Train>();
});

Em um bloco de atualização de assinatura, você pode remover todas as assinaturas sem nome do conjunto de assinaturas com MutableSubscriptionSet.clear().

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.clear();
});

Mutar o conjunto de assinaturas em um bloco de atualização é apenas uma parte da alteração de uma assinatura. Após a alteração da assinatura local, o Realm sincroniza com o servidor para resolver quaisquer atualizações nos dados devido à alteração da assinatura. Isso inclui adicionar ou remover dados do domínio sincronizado.

Use Realm.subscriptions.waitForSynchronization() para aguardar o servidor confirmar este conjunto de assinaturas. Se o servidor rejeitar a alteração e uma exceção for lançada.

Uma exceção pode ocorrer se:

  • Você se inscreve em uma query não suportada. A assinatura de uma query não suportada pausará a sincronização. Para retomar a sincronização, remova a query não suportada.

  • Você está executando uma ação inválida, como adicionar um objeto que não corresponde a uma assinatura. Este Atlas Triggers um reinício do cliente: os dados são apagados do domínio e uma nova cópia dos dados é criada sem nenhuma assinatura no conjunto.

await realm.subscriptions.waitForSynchronization();

Use o realm.subscriptions.state propriedade para ler o estado atual do conjunto de assinaturas.

O superseded estado é um SubscriptionSetState que pode ocorrer quando outro thread atualiza uma assinatura em uma instância diferente do conjunto de assinatura. Se o estado se tornar superseded, você deverá obter uma nova instância do conjunto de assinaturas antes de poder atualizá-lo.

Observação

Estado da assinatura "Concluído"

O estado do conjunto de assinaturas "complete" não significa que a sincronização "está concluída" ou "todos os documentos foram sincronizados". "Completo" significa que as duas coisas a seguir aconteceram:

  • A assinatura se tornou o conjunto de assinaturas ativo que está sendo atualmente sincronizado com o servidor.

  • Os documentos que correspondiam à assinatura no momento em que a assinatura foi enviada ao servidor agora estão no dispositivo local. Observe que isso não inclui necessariamente todos os documentos que atualmente correspondem à assinatura.

O SDK do Realm não fornece uma maneira de verificar se todos os documentos que correspondem a uma assinatura foram sincronizados com o dispositivo.

Adicionar um campo de query indexado à sua aplicação pode melhorar o desempenho de queries simples em dados fortemente particionados. Por exemplo, uma aplicação onde as queries mapeiam fortemente os dados para um dispositivo, armazém ou usuário, como user_id == $0, “641374b03725038381d2e1fb”, é uma boa candidata para um campo de query indexado. No entanto, um campo de query indexado tem requisitos específicos para uso em uma inscrição de query:

  • O campo de query indexado deve ser usado em todas as inscrições de query. Não pode estar faltando na query.

  • O campo de query indexado deve usar uma comparação == ou IN com uma constante pelo menos uma vez na query de inscrição. Por exemplo, user_id == $0, "641374b03725038381d2e1fb" ou store_id IN $0, {1,2,3}.

Opcionalmente, você pode incluir uma comparação AND, desde que o campo consultável indexado seja comparado diretamente com uma constante usando == ou IN pelo menos uma vez. Por exemplo, store_id IN {1,2,3} AND region=="Northeast" ou store_id == 1 AND (active_promotions < 5 OR num_employees < 10).

As consultas inválidas do Flexible Sync em um campo indexado que pode ser consultado incluem consultas em que:

  • O campo de consulta indexado não utiliza AND com o resto da consulta. Por exemplo store_id IN {1,2,3} OR region=="Northeast" é inválido porque usa OR em vez de AND. Da mesma forma, store_id == 1 AND active_promotions < 5 OR num_employees < 10 é inválido porque o AND só se aplica ao termo ao lado, não à consulta inteira.

  • O campo de consulta indexado não é utilizado em um operador de igualdade. Por exemplo store_id > 2 AND region=="Northeast" é inválido porque utiliza apenas o operador > com o campo de consulta indexado e não tem uma comparação de igualdade.

  • A query está totalmente ausente do campo de query indexado. Por exemplo, region=="Northeast ou truepredicate são inválidos porque não contêm o campo de query indexado.

A Flexible Sync tem algumas limitações ao usar operadores RQL. Quando você escreve a assinatura de consulta que determina quais dados sincronizar, o servidor não oferece suporte a esses operadores de consulta. No entanto, você ainda pode usar toda a gama de recursos de RQL para consultar o conjunto de dados sincronizado no aplicativo cliente.

Tipo de operador
Operadores não suportados
Operadores agregados
@avg, @count, @max, @min, @sum
Sufixos de query
DISTINCT, SORT , LIMIT

Queries que não diferenciam maiúsculas de minúsculas ([c]) não podem usar índices de forma eficaz. Sendo assim, queries que não diferenciam maiúsculas de minúsculas não são recomendadas, pois podem causar problemas de desempenho.

A sincronização flexível suporta apenas @count para campos de array.

A sincronização flexível oferece suporte às listas de query usando o operador IN .

Você pode consultar uma lista de constantes para ver se ela contém o valor de um campo de consulta:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

Se um campo de query tiver um valor de array, você poderá consultar para ver se ele contém um valor constante:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

Aviso

Não é possível comparar duas listas entre si em uma consulta de sincronização flexível. Observe que esta é uma sintaxe válida do Realm Query Language fora das consultas do Flexible Sync.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

A Flexible Sync não oferece suporte à consulta de propriedades em objetos ou links embarcados. Por exemplo, obj1.field == "foo".

O limite de tamanho para qualquer assinatura de query em seu conjunto de assinatura é de 256 kB. Exceder esse limite resulta em um erro de LimitsExceeded.

O gerenciamento de várias assinaturas com a API .subscribe() descrita na seção Assinar queries é menos eficiente do que executar atualizações em lote quando você gerencia assinaturas manualmente por meio da API do conjunto de assinaturas. Para obter melhor desempenho ao fazer várias alterações na assinatura, use a API subscriptions.update descrita na seção Gerenciar assinaturas manualmente .

Cada transação de escrita para um conjunto de assinaturas tem um custo de desempenho. Se você precisar fazer várias atualizações em um objeto do Realm durante uma sessão, considere manter objetos editados na memória até que todas as alterações sejam concluídas. Isso melhora o desempenho da sincronização, gravando apenas o objeto completo e atualizado em seu domínio, em vez de cada alteração.

Voltar

Abrir realm sincronizado