Tutorial: sincronização delta - AWS AppSync

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Tutorial: sincronização delta

nota

Agora, oferecemos suporte principalmente ao runtime do APPSYNC_JS e sua documentação. Considere usar o runtime do APPSYNC_JS e seus guias disponíveis aqui.

Aplicativos clientes no AWS AppSync armazenam dados armazenando em cache as respostas do GraphQL localmente no disco em um aplicativo móvel/web. As fontes de dados e as operações Sync versionadas oferecem aos clientes a capacidade de executar o processo de sincronização usando um único resolvedor. Isso permite que os clientes hidratem o cache local com resultados de uma consulta base que possa ter muitos registros e receba apenas os dados alterados desde a última consulta (as atualizações delta). Ao permitir que os clientes executem a hidratação base do cache com uma solicitação inicial e atualizações adicionais em outra consulta, você pode mover o cálculo do aplicativo cliente para o back-end. Isso é muito mais eficiente para aplicativos cliente que alternam com frequência entre estados online e offline.

Para implementar a Sincronização delta, a consulta Sync usa a operação Sync em uma fonte de dados versionada. Quando uma mutação do AWS AppSync altera um item em uma fonte de dados versionada, um registro dessa alteração também será armazenado na tabela Delta. Você pode optar por usar diferentes tabelas Delta (por exemplo, uma por tipo, uma por área de domínio) para outras fontes de dados versionadas, ou uma única tabela Delta para a API. AWS O AppSync não recomenda o uso de uma única tabela Delta para várias APIs para evitar a colisão de chaves primárias.

Além disso, os clientes de Sincronização delta também podem receber uma assinatura como um argumento, e a assinatura de coordenadas do cliente se reconecta e realiza gravações entre transições offline para online. A Sincronização delta realiza isso recuperando automaticamente as assinaturas (incluindo recuo exponencial e nova tentativa com tremulação por meio de diferentes cenários de erro de rede) e armazenando eventos em uma fila. A consulta delta ou base apropriada é executada antes de mesclar quaisquer eventos da fila e, finalmente, processar as assinaturas normalmente.

A documentação das opções de configuração do cliente incluindo o Amplify DataStore, está disponível no site da Amplify Framework. Essa documentação descreve como configurar operações Sync e fontes de dados versionadas do DynamoDB para trabalhar com o cliente de Sincronização delta para obter acesso ideal aos dados.

Configuração com um clique

Para configurar automaticamente o endpoint do GraphQL no AWS AppSync com todos os resolvedores configurados e os recursos necessários da AWS, use o seguinte modelo do AWS CloudFormation.

Esta pilha cria os seguintes recursos na sua conta:

  • 2 Tabelas do DynamoDB (Base e Delta)

  • 1 API do AWS AppSync com chave de API

  • 1 Perfil do IAM com política para tabelas do DynamoDB

Duas tabelas são usadas para particionar suas consultas de sincronização em uma segunda tabela que atua como um diário de eventos que foram perdidos quando os clientes estavam offline. Para manter as consultas eficientes na tabela delta, os TTLs do Amazon DynamoDB são usados para preparar automaticamente os eventos conforme necessário. O tempo TTL é configurável para suas necessidades na fonte de dados (você pode querer que ele tenha 1 hora, 1 dia etc.).

Esquema

Para demonstrar a Sincronização delta, o exemplo de aplicativo cria um esquema de Postagens baseado nas tabelas Base e Delta no DynamoDB. AWS O AppSync grava automaticamente as mutações em ambas as tabelas. A consulta de sincronização obtêm registros da tabela Base ou Delta, conforme apropriado, e uma única assinatura é definida para mostrar como os clientes podem aproveitar isso em sua lógica de reconexão.

input CreatePostInput { author: String! title: String! content: String! url: String ups: Int downs: Int _version: Int } interface Connection { nextToken: String startedAt: AWSTimestamp! } type Mutation { createPost(input: CreatePostInput!): Post updatePost(input: UpdatePostInput!): Post deletePost(input: DeletePostInput!): Post } type Post { id: ID! author: String! title: String! content: String! url: AWSURL ups: Int downs: Int _version: Int _deleted: Boolean _lastChangedAt: AWSTimestamp! } type PostConnection implements Connection { items: [Post!]! nextToken: String startedAt: AWSTimestamp! } type Query { getPost(id: ID!): Post syncPosts(limit: Int, nextToken: String, lastSync: AWSTimestamp): PostConnection! } type Subscription { onCreatePost: Post @aws_subscribe(mutations: ["createPost"]) onUpdatePost: Post @aws_subscribe(mutations: ["updatePost"]) onDeletePost: Post @aws_subscribe(mutations: ["deletePost"]) } input DeletePostInput { id: ID! _version: Int! } input UpdatePostInput { id: ID! author: String title: String content: String url: String ups: Int downs: Int _version: Int! } schema { query: Query mutation: Mutation subscription: Subscription }

O esquema do GraphQL é padrão, mas vale a pena chamar alguns itens antes de avançar. Primeiro, todas as mutações, automaticamente, primeiro gravam na tabela Base e depois na tabela Delta . A tabela Base é a fonte confiável principal do estado, enquanto a tabela Delta é o diário. Se você não passa no lastSync: AWSTimestamp, a consulta syncPosts é executada na tabela Base e hidrata o cache, além de ser executada em períodos como um processo de recuperação global para casos de borda quando os clientes ficam off-line por mais tempo que o período de TTL configurado na tabela Delta. Se você passa no lastSync: AWSTimestamp, a consulta syncPosts é executada em sua tabela Delta e é usada pelos clientes para recuperar eventos alterados desde a última vez que eles ficaram off-line. Amplificar os clientes passa automaticamente o valor lastSync: AWSTimestamp e persiste no disco adequadamente.

O campo _deleted em Postagens é usado para operações DELETE. Quando os clientes estão off-line e os registros são removidos da tabela Base, esse atributo notifica os clientes que executam a sincronização para remover itens de seu cache local. Nos casos em que os clientes ficam off-line por períodos mais longos e o item foi removido antes que o cliente possa recuperar esse valor com uma consulta de Sincronização delta, o evento de recuperação global na consulta base (configurável no cliente) será executado e remove o item do cache. Esse campo é marcado como opcional porque retorna um valor apenas ao executar uma consulta de sincronização que tenha itens excluídos presentes.

Mutações

Para todas as mutações, o AWS AppSync faz uma operação padrão Criar/Atualizar/Excluir na tabela Base, além de registrar a alteração na tabela Delta automaticamente. Você pode reduzir ou aumentar o tempo para manter registros, modificando o valor DeltaSyncTableTTL na fonte de dados. Para organizações com alta velocidade de dados, pode ser adequado manter o tempo reduzido. Como alternativa, se seus clientes estiverem off-line por períodos mais longos, convém manter por mais tempo.

Consultas de sincronização

A consulta base é uma operação de sincronização do DynamoDB sem um valor lastSync especificado. Para muitas organizações, isso funciona porque a consulta base só é executada na inicialização e periodicamente depois disso.

A consulta delta é uma operação de sincronização do DynamoDB com um valor lastSync especificado. A consulta delta é executada sempre que o cliente volta a ficar online de um estado offline (desde que o período da consulta base não tenha sido acionado para execução). Os clientes rastreiam automaticamente a última vez que executaram com êxito uma consulta para sincronizar dados.

Quando uma consulta delta é executada, o resolvedor da consulta usa o ds_pk e o ds_sk para consultar somente os registros que foram alterados desde a última sincronização executada pelo cliente. O cliente armazena a resposta apropriada do GraphQL.

Para obter mais informações sobre como executar consultas de sincronização, consulte a documentação da Operação de sincronização.

Exemplo

Vamos começar chamando uma mutação createPost para criar um item:

mutation create { createPost(input: {author: "Nadia", title: "My First Post", content: "Hello World"}) { id author title content _version _lastChangedAt _deleted } }

O valor de retorno dessa mutação será o seguinte:

{ "data": { "createPost": { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "My First Post", "content": "Hello World", "_version": 1, "_lastChangedAt": 1574469356331, "_deleted": null } } }

Se examinar o conteúdo da tabela Base, você verá um registro semelhante a:

{ "_lastChangedAt": { "N": "1574469356331" }, "_version": { "N": "1" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "My First Post" } }

Se examinar o conteúdo da tabela Delta, você verá um registro semelhante a:

{ "_lastChangedAt": { "N": "1574469356331" }, "_ttl": { "N": "1574472956" }, "_version": { "N": "1" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "ds_pk": { "S": "AppSync-delta-sync-post:2019-11-23" }, "ds_sk": { "S": "00:35:56.331:81d36bbb-1579-4efe-92b8-2e3f679f628b:1" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "My First Post" } }

Agora podemos simular uma consulta Base que será executada pelo cliente para hidratar seu armazenamento de dados local usando uma consulta syncPosts como:

query baseQuery { syncPosts(limit: 100, lastSync: null, nextToken: null) { items { id author title content _version _lastChangedAt } startedAt nextToken } }

O valor de retorno dessa consulta Base será o seguinte:

{ "data": { "syncPosts": { "items": [ { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "My First Post", "content": "Hello World", "_version": 1, "_lastChangedAt": 1574469356331 } ], "startedAt": 1574469602238, "nextToken": null } } }

Salvaremos o valor startedAt posteriormente para simular uma consulta Delta, mas primeiro precisamos fazer uma alteração em nossa tabela. Usaremos a mutação updatePost para modificar nossa Postagem existente:

mutation updatePost { updatePost(input: {id: "81d36bbb-1579-4efe-92b8-2e3f679f628b", _version: 1, title: "Actually this is my Second Post"}) { id author title content _version _lastChangedAt _deleted } }

O valor de retorno dessa mutação será o seguinte:

{ "data": { "updatePost": { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "Actually this is my Second Post", "content": "Hello World", "_version": 2, "_lastChangedAt": 1574469851417, "_deleted": null } } }

Se examinar o conteúdo da tabela Base agora, você verá o item atualizado:

{ "_lastChangedAt": { "N": "1574469851417" }, "_version": { "N": "2" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "Actually this is my Second Post" } }

Se examinar o conteúdo da tabela Delta agora, você verá dois registros:

  1. Um registro quando o item foi criado

  2. Um registro de quando o item foi atualizado.

O novo item será semelhante a:

{ "_lastChangedAt": { "N": "1574469851417" }, "_ttl": { "N": "1574473451" }, "_version": { "N": "2" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "ds_pk": { "S": "AppSync-delta-sync-post:2019-11-23" }, "ds_sk": { "S": "00:44:11.417:81d36bbb-1579-4efe-92b8-2e3f679f628b:2" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "Actually this is my Second Post" } }

Agora podemos simular uma consulta Delta para recuperar modificações que ocorreram quando um cliente estava offline. Usaremos o valor startedAt retornado de nossa consulta Base para fazer a solicitação:

query delta { syncPosts(limit: 100, lastSync: 1574469602238, nextToken: null) { items { id author title content _version } startedAt nextToken } }

O valor de retorno dessa consulta Delta será o seguinte:

{ "data": { "syncPosts": { "items": [ { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "Actually this is my Second Post", "content": "Hello World", "_version": 2 } ], "startedAt": 1574470400808, "nextToken": null } } }