

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.

# Utilisation des opérations Delta Sync sur des sources de données versionnées dans AWS AppSync
<a name="tutorial-delta-sync"></a>

**Note**  
Nous prenons désormais principalement en charge le runtime APPSYNC\$1JS et sa documentation. [Pensez à utiliser le runtime APPSYNC\$1JS et ses guides ici.](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html)

Les applications clientes AWS AppSync stockent les données en mettant en cache les réponses GraphQL localement sur le disque d'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 votre API. 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](https://aws-amplify.github.io/) 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
<a name="one-click-setup"></a>

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 

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/deltasync/deltasync-v2-full.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/deltasync/deltasync-v2-full.yaml) 

Cette pile crée les ressources suivantes dans votre compte :
+ 2 tables DynamoDB (Base et Delta)
+ 1 AWS AppSync API avec clé d'API
+ 1 rôle IAM 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](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html) est utilisé pour organiser automatiquement les événements selon les besoins. L'heure TTL est configurable pour vos besoins sur la source de données (vous pouvez définir 1 heure, 1 jour, etc.).

## Schema
<a name="schema"></a>

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 passez pas dans la `lastSync: AWSTimestamp`, la requête `syncPosts` s'exécute sur la table de *Base* et hydrate le cache tout en s'exécutant périodiquement en tant que *processus de rattrapage global* pour les cas limites où les clients sont hors ligne plus longtemps que le temps TTL que vous aviez 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 *\$1deleted* sur *Post* est utilisé pour **SUPPRIMER** des opé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
<a name="mutations"></a>

Pour toutes les mutations, AWS AppSync effectue une Create/Update/Delete opération standard 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
<a name="sync-queries"></a>

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](aws-appsync-conflict-detection-and-sync-sync-operations.md).

## Exemple
<a name="example"></a>

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

1. 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
    }
  }
}
```