Tutoriel : Utilisation des opérations Delta Sync sur des sources de données versionnées - AWS AppSync

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Tutoriel : Utilisation des opérations Delta Sync sur des sources de données versionnées

Note

Nous prenons désormais principalement en charge le runtime APPSYNC _JS et sa documentation. Pensez à utiliser le runtime APPSYNC _JS et ses guides ici.

Les applications clientes AWS AppSync stockent les données en mettant en cache les réponses GraphQL localement sur le disque dans une application mobile/Web. Les sources de données et les opérations Sync versionnées permettent aux clients d'effectuer le processus de synchronisation à l'aide d'un seul résolveur. Cela permet aux clients de remplir leur cache local avec les résultats d'une requête de base pouvant comprendre un grand nombre d'enregistrements, puis de recevoir uniquement les données modifiées depuis leur dernière requête (les mises à jour delta). En permettant aux clients de séparer l'hydratation de base du cache avec une demande initiale et les mises à jour incrémentielles d'une autre demande, vous pouvez déplacer le calcul de votre application cliente vers le backend. Ceci est nettement plus efficace pour les applications clientes qui basculent fréquemment entre les états en ligne et hors ligne.

Pour implémenter Delta Sync, la requête Sync utilise l'opération Sync sur une source de données versionnée. Lorsqu'une AWS AppSync mutation modifie un élément dans une source de données versionnée, un enregistrement de cette modification est également stocké dans la table Delta. Vous pouvez choisir d'utiliser différentes tables Delta (par exemple, une par type, une par domaine) pour les autres sources de données versionnées ou une seule table Delta pour votreAPI. AWS AppSync recommande de ne pas utiliser une seule table Delta pour plusieurs APIs afin d'éviter la collision des clés primaires.

En outre, les clients Delta Sync peuvent également recevoir un abonnement en tant qu'argument, puis les coordonne l'abonnement et écrit entre les transitions en lige et hors ligne. Delta Sync effectue cette opération en relançant automatiquement les abonnements, notamment le backoff exponentiel et réessaie avec une instabilité via différents scénarios d'erreur et le stockage des événements dans une file d'attente. La requête de base ou delta appropriée est ensuite exécutée avant de fusionner des événements de la file d'attente, puis de traiter les abonnements normalement.

La documentation des options de configuration du client, y compris l'Amplify DataStore, est disponible sur le site Web Amplify Framework. Cette documentation explique comment configurer les sources de données DynamoDB versionnées et les opérations Sync pour qu'elles fonctionnent avec le client Delta Sync pour un accès optimal aux données.

Configuration en un clic

Pour configurer automatiquement le point de terminaison GraphQL AWS AppSync avec tous les résolveurs configurés et les AWS ressources nécessaires, utilisez ce modèle : AWS CloudFormation

Blue button labeled "Launch Stack" with an arrow icon indicating an action to start.

Cette pile crée les ressources suivantes dans votre compte :

  • 2 tables DynamoDB (Base et Delta)

  • 1 AWS AppSync API avec API clé

  • 1 IAM Rôle avec politique pour les tables DynamoDB

Deux tables sont utilisées pour partitionner vos requêtes de synchronisation dans une seconde table agissant comme un journal d'événements manqués lorsque les clients étaient hors ligne. Pour garantir l'efficacité des requêtes sur la table delta, Amazon TTLs DynamoDB est utilisé pour organiser automatiquement les événements selon les besoins. L'TTLheure est configurable en fonction de vos besoins sur la source de données (vous pouvez choisir une heure, un jour, etc.).

Schema

Pour illustrer Delta Sync, l'exemple d'application crée un schéma Posts basé sur une table Base et Delta dans DynamoDB. AWS AppSync écrit automatiquement les mutations dans les deux tables. La requête de synchronisation tire des enregistrements des tables de Base ou Delta selon les besoins, et un seul abonnement est défini pour montrer comment les clients peuvent en tirer parti dans leur logique de reconnexion.

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 }

Le schéma GraphQL est standard, mais il peut être nécessaire d'appeler avant de continuer, pour deux raisons. Tout d'abord, toutes les mutations écrivent automatiquement dans la table Base en premier lieu, puis dans la table Delta. La table de Base est la source de vérité centrale pour l'état tandis que la table Delta est votre journal. Si vous ne transmettez pas lelastSync: AWSTimestamp, la syncPosts requête s'exécute sur la table de base et hydrate le cache. Elle s'exécute périodiquement dans le cadre d'un processus de rattrapage global pour les cas extrêmes où les clients sont hors ligne plus longtemps que le TTL temps que vous avez configuré dans la table Delta. Si vous passez dans le lastSync: AWSTimestamp, la requête syncPosts s'exécute sur votre table Delta et est utilisée par les clients pour récupérer des événements modifiés la dernière fois qu'ils étaient hors ligne. Les clients Amplify transmettent automatiquement la valeur lastSync: AWSTimestamp et persistent sur le disque de manière appropriée.

Le champ _deleted sur Post est utilisé pour les DELETEopérations. Lorsque des clients sont hors ligne et que des enregistrements sont supprimés de la table Base, cet attribut informe les clients effectuant la synchronisation d'expulser les éléments de leur cache local. Si des clients sont hors ligne pour de plus longues périodes et que l'élément a été supprimé avant que le client ne récupère cette valeur avec une requête Delta Sync, l'événement de rattrapage global dans la requête de base (configurable dans le client), s'exécute et supprime l'élément à partir du cache. Ce champ est marqué comme facultatif car il ne renvoie de valeur que lors de l'exécution d'une requête de synchronisation ayant supprimé les objets présents.

Mutations

Pour toutes les mutations, AWS AppSync effectue une opération standard de création/mise à jour/suppression dans la table de base et enregistre également automatiquement la modification dans la table Delta. Vous pouvez réduire ou prolonger la période de conservation des enregistrements en modifiant la valeur DeltaSyncTableTTL sur la source de données. Pour les organisations avec une vitesse de données élevée, il est recommandé de la garder courte. Si vos clients sont hors ligne plus longtemps, il peut être prudent de la garder plus longue.

Requêtes de synchronisation

La requête de base est une opération DynamoDB Sync sans lastSync valeur spécifiée. Cela fonctionne pour de nombreuses organisations car la requête de base ne s'exécute qu'au démarrage et par la suite, à intervalles réguliers.

La requête delta est une opération de synchronisation DynamoDB avec lastSync une valeur spécifiée. La requête delta s'exécute chaque fois que le client se reconnecte alors qu'il était hors ligne (à condition que le temps périodique de requête de base n'ait pas déclenchée l'exécution). Les clients suivent automatiquement la dernière fois qu'ils ont exécuté une requête pour synchroniser les données.

Lorsqu'une requête delta est exécutée, le résolveur de la requête utilise ds_pk et ds_sk pour interroger uniquement les enregistrements qui ont changé depuis la dernière synchronisation par le client. Le client stocke la réponse GraphQL appropriée.

Pour de plus amples informations sur l'exécution des requêtes de synchronisation, veuillez consulter la documentation Opération de synchronisation.

Exemple

Commençons d'abord par appeler une mutation createPost pour créer un élément :

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

La valeur de retour de cette mutation sera la suivante :

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

Si vous examinez le contenu de la table Base, vous verrez un enregistrement qui ressemble à :

{ "_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" } }

Si vous examinez le contenu de la table Delta, vous verrez un enregistrement qui ressemble à :

{ "_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" } }

Maintenant, nous pouvons simuler une requête de base qu'un client va exécuter pour hydrater son magasin de données local en utilisant une requête syncPosts comme :

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

La valeur de retour de cette requête de base sera la suivante :

{ "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 } } }

Nous enregistrerons la valeur startedAt plus tard pour simuler une requête Delta mais nous devons d'abord apporter une modification à notre table. Utilisons la mutation updatePost pour modifier notre publication existante :

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 } }

La valeur de retour de cette mutation sera la suivante :

{ "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 } } }

Si vous examinez maintenant le contenu de la table Base vous devriez voir l'élément mis à jour :

{ "_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" } }

Si vous examinez maintenant le contenu de la table Delta, vous devriez voir deux enregistrements :

  1. Enregistrement lors de la création de l'élément

  2. Enregistrement de la date à laquelle l'élément a été mis à jour.

Le nouvel élément ressemblera à :

{ "_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" } }

Maintenant, nous pouvons simuler une requête Delta pour récupérer les modifications qui se sont produites lorsqu'un client était hors ligne. Nous utiliserons la valeur startedAt renvoyée par notre requête de Base pour effectuer la requête :

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

La valeur de retour de cette requête Delta sera la suivante :

{ "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 } } }