Utilisation des opérations par lots DynamoDB dans AWS AppSync - 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.

Utilisation des opérations par lots DynamoDB dans AWS AppSync

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.

AWS AppSync prend en charge l'utilisation des opérations par lots Amazon DynamoDB sur une ou plusieurs tables d'une même région. Les opérations prises en charge sont BatchGetItem, BatchPutItem et BatchDeleteItem. En utilisant ces fonctionnalités dans AWS AppSync, vous pouvez effectuer des tâches telles que :

  • Transmission d'une liste de clés dans une seule requête et renvoi des résultats à partir d'une table

  • Lecture des enregistrements à partir d'une ou plusieurs tables dans une seule requête

  • Écriture des enregistrements en bloc dans une ou plusieurs tables

  • Écriture ou suppression des enregistrements sous condition dans plusieurs tables pouvant avoir une relation

L'utilisation d'opérations par lots avec AWS AppSync DynamoDB est une technique avancée qui nécessite un peu plus de réflexion et de connaissance des opérations de votre backend et des structures de tables. En outre, les opérations par lots AWS AppSync présentent deux différences majeures par rapport aux opérations non groupées :

  • Le rôle de la source de données doit disposer d'autorisations sur toutes les tables auxquelles le résolveur doit accéder.

  • La spécification de table d'un résolveur fait partie du modèle de mappage.

Autorisations

Comme les autres résolveurs, vous devez créer une source de données dans AWS AppSync et soit créer un rôle, soit utiliser un rôle existant. Les opérations par lots nécessitant des autorisations différentes sur les tables DynamoDB, vous devez accorder au rôle configuré des autorisations pour les actions de lecture ou d'écriture :

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:account:table/TABLENAME", "arn:aws:dynamodb:region:account:table/TABLENAME/*" ] } ] }

Remarque : Les rôles sont liés aux sources de données dans une source de données AWS AppSync, et les résolveurs de champs sont invoqués par rapport à une source de données. Pour simplifier la configuration, une seule table est spécifiée pour les sources de données configurées pour effectuer une extraction par rapport à DynamoDB. Par conséquent, lorsque vous effectuez une opération de traitement par lots sur plusieurs tables dans un seul résolveur (ce qui constitue une tâche plus avancée), vous devez accorder au rôle associé à cette source de données l'accès à toutes les tables avec lesquelles le résolveur devra interagir. Cela se ferait dans le champ Ressource de la IAM politique ci-dessus. La configuration des tables sur lesquelles les appels par lots doivent être effectués doit être définie dans le modèle de résolveur, dont vous trouverez la description ci-dessous.

Source de données

Dans un souci de simplicité, nous allons utiliser la même source de données pour tous les résolveurs utilisés dans ce didacticiel. Dans l'onglet Sources de données, créez une nouvelle source de données DynamoDB et nommez-la. BatchTutorial Le nom de la table peut être quelconque, car les noms de table sont spécifiés dans le cadre du modèle de mappage de demande pour les opérations par lots. Nous allons nommer la table empty.

Dans le cadre de ce didacticiel, n'importe quel rôle avec la stratégie en ligne suivante fonctionne :

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:account:table/Posts", "arn:aws:dynamodb:region:account:table/Posts/*", "arn:aws:dynamodb:region:account:table/locationReadings", "arn:aws:dynamodb:region:account:table/locationReadings/*", "arn:aws:dynamodb:region:account:table/temperatureReadings", "arn:aws:dynamodb:region:account:table/temperatureReadings/*" ] } ] }

Traitement par lots sur une table unique

Avertissement

BatchPutItemet ne BatchDeleteItem sont pas pris en charge lorsqu'ils sont utilisés avec la détection et la résolution de conflits. Ces paramètres doivent être désactivés pour éviter d'éventuelles erreurs.

Pour cet exemple, supposons que vous ayez une seule table nommée Posts dans laquelle vous souhaitez ajouter et supprimer des éléments via des opérations par lots. Utilisez le schéma suivant, en notant que pour la requête, nous transmettrons une liste de IDs :

type Post { id: ID! title: String } input PostInput { id: ID! title: String } type Query { batchGet(ids: [ID]): [Post] } type Mutation { batchAdd(posts: [PostInput]): [Post] batchDelete(ids: [ID]): [Post] } schema { query: Query mutation: Mutation }

Attachez un résolveur au champ batchAdd() avec le modèle de mappage de demande suivant. Ce processus prend automatiquement chaque élément du type GraphQL input PostInput et crée une mappe, qui est nécessaire pour l'opération BatchPutItem :

#set($postsdata = []) #foreach($item in ${ctx.args.posts}) $util.qr($postsdata.add($util.dynamodb.toMapValues($item))) #end { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { "Posts": $utils.toJson($postsdata) } }

Dans cet exemple, le modèle de mappage de réponse est une simple transmission, mais le nom de la table est ajouté sous la forme ..data.Posts à l'objet de contexte :

$util.toJson($ctx.result.data.Posts)

Accédez maintenant à la page Requêtes de la AWS AppSync console et exécutez la batchAddmutation suivante :

mutation add { batchAdd(posts:[{ id: 1 title: "Running in the Park"},{ id: 2 title: "Playing fetch" }]){ id title } }

Vous devriez voir les résultats imprimés à l'écran et vous pouvez valider indépendamment via la console DynamoDB que les deux valeurs ont été écrites dans la table Posts.

Attachez ensuite un résolveur au champ batchGet() avec le modèle de mappage de demande suivant. Ce processus prend automatiquement chaque élément du type GraphQL ids:[] et crée une mappe, qui est nécessaire pour l'opération BatchGetItem :

#set($ids = []) #foreach($id in ${ctx.args.ids}) #set($map = {}) $util.qr($map.put("id", $util.dynamodb.toString($id))) $util.qr($ids.add($map)) #end { "version" : "2018-05-29", "operation" : "BatchGetItem", "tables" : { "Posts": { "keys": $util.toJson($ids), "consistentRead": true, "projection" : { "expression" : "#id, title", "expressionNames" : { "#id" : "id"} } } } }

Le modèle de mappage de réponse est à nouveau une simple transmission, avec une fois encore le nom de la table ajouté sous la forme ..data.Posts à l'objet de contexte :

$util.toJson($ctx.result.data.Posts)

Retournez maintenant à la page Requêtes de la AWS AppSync console et exécutez la batchGet requête suivante :

query get { batchGet(ids:[1,2,3]){ id title } }

Vous devez obtenir les résultats des deux valeurs id que vous avez ajoutées précédemment. Notez la valeur null renvoyée pour l'élément id de valeur 3. Cela s'explique par le fait qu'il n'y avait encore aucun enregistrement de votre table Posts ayant cette valeur. Notez également que cela AWS AppSync renvoie les résultats dans le même ordre que les clés transmises à la requête, ce qui est une fonctionnalité supplémentaire qui le AWS AppSync fait en votre nom. Par conséquent, si vous basculez vers batchGet(ids:[1,3,2), vous verrez l'ordre modifié. Vous saurez également quel id a renvoyé une valeur null.

Enfin, attachez un résolveur au champ batchDelete() avec le modèle de mappage de demande suivant. Ce processus prend automatiquement chaque élément du type GraphQL ids:[] et crée une mappe, qui est nécessaire pour l'opération BatchGetItem :

#set($ids = []) #foreach($id in ${ctx.args.ids}) #set($map = {}) $util.qr($map.put("id", $util.dynamodb.toString($id))) $util.qr($ids.add($map)) #end { "version" : "2018-05-29", "operation" : "BatchDeleteItem", "tables" : { "Posts": $util.toJson($ids) } }

Le modèle de mappage de réponse est à nouveau une simple transmission, avec une fois encore le nom de la table ajouté sous la forme ..data.Posts à l'objet de contexte :

$util.toJson($ctx.result.data.Posts)

Retournez maintenant à la page Requêtes de la AWS AppSync console et exécutez la batchDeletemutation suivante :

mutation delete { batchDelete(ids:[1,2]){ id } }

Les enregistrements contenant les id 1 et 2 doivent désormais avoir été supprimés. Si vous exécutez à nouveau la requête batchGet() à partir de l'état précédent, le résultat renvoyé devrait être null.

Traitement par lots sur plusieurs tables

Avertissement

BatchPutItemet ne BatchDeleteItem sont pas pris en charge lorsqu'ils sont utilisés avec la détection et la résolution de conflits. Ces paramètres doivent être désactivés pour éviter d'éventuelles erreurs.

AWS AppSync vous permet également d'effectuer des opérations par lots sur plusieurs tables. Créons un application plus complexe. Imaginez que nous construisions une application traitant de la santé des animaux domestiques (nommée Pet Health), où des capteurs signalent l'emplacement et la température corporelle des animaux. Les capteurs sont alimentés par piles et tentent de se connecter au réseau toutes les deux ou trois minutes. Lorsqu'un capteur établit une connexion, il envoie ses relevés à notre AWS AppSync API. Des déclencheurs analysent alors les données afin de pouvoir transmettre un tableau de bord au propriétaire de l'animal. Concentrons-nous sur la représentation des interactions entre le capteur et le magasin de données backend.

Comme condition préalable, créons d'abord deux tables DynamoDB locationReadings; elles stockeront les relevés de position des capteurs temperatureReadingset les relevés de température des capteurs. Les deux tables partagent la même structure de clé primaire : sensorId (String) étant la clé de partition et timestamp (String) étant la clé de tri.

Nous allons utiliser le schéma GraphQL suivant :

type Mutation { # Register a batch of readings recordReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult # Delete a batch of readings deleteReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult } type Query { # Retrieve all possible readings recorded by a sensor at a specific time getReadings(sensorId: ID!, timestamp: String!): [SensorReading] } type RecordResult { temperatureReadings: [TemperatureReading] locationReadings: [LocationReading] } interface SensorReading { sensorId: ID! timestamp: String! } # Sensor reading representing the sensor temperature (in Fahrenheit) type TemperatureReading implements SensorReading { sensorId: ID! timestamp: String! value: Float } # Sensor reading representing the sensor location (lat,long) type LocationReading implements SensorReading { sensorId: ID! timestamp: String! lat: Float long: Float } input TemperatureReadingInput { sensorId: ID! timestamp: String value: Float } input LocationReadingInput { sensorId: ID! timestamp: String lat: Float long: Float }

BatchPutItem - Enregistrement des lectures des capteurs

Nos capteurs doivent être en mesure d'envoyer leurs relevés une fois qu'ils sont connectés à Internet. Le champ GraphQL Mutation.recordReadings est celui API qu'ils utiliseront pour ce faire. Attachons un résolveur pour nous API donner vie.

Sélectionnez Attach (Attacher) en regard du champ Mutation.recordReadings. Sur l'écran suivant, sélectionnez la source de données BatchTutorial créée au début du didacticiel.

Nous ajoutons ensuite le modèle de mappage de demande suivant :

Modèle de mappage de demande

## Convert tempReadings arguments to DynamoDB objects #set($tempReadings = []) #foreach($reading in ${ctx.args.tempReadings}) $util.qr($tempReadings.add($util.dynamodb.toMapValues($reading))) #end ## Convert locReadings arguments to DynamoDB objects #set($locReadings = []) #foreach($reading in ${ctx.args.locReadings}) $util.qr($locReadings.add($util.dynamodb.toMapValues($reading))) #end { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { "locationReadings": $utils.toJson($locReadings), "temperatureReadings": $utils.toJson($tempReadings) } }

Comme vous pouvez le voir, l'opération BatchPutItem nous permet de spécifier plusieurs tables.

Nous utilisons ensuite le modèle de mappage de réponse suivant :

Modèle de mappage de réponse

## If there was an error with the invocation ## there might have been partial results #if($ctx.error) ## Append a GraphQL error for that field in the GraphQL response $utils.appendError($ctx.error.message, $ctx.error.message) #end ## Also returns data for the field in the GraphQL response $utils.toJson($ctx.result.data)

Les opérations par lots peuvent renvoyer à la fois des erreurs et des résultats à la suite de l'appel. Dans ce cas, nous pouvons effectuer certaines opérations de traitement des erreurs supplémentaires.

Remarque : L'utilisation de $utils.appendError() est similaire à celle de $util.error(), la principale différence résidant dans le fait qu'il n'interrompt pas l'évaluation du modèle de mappage. Au lieu de cela, il signale qu'une erreur s'est produite avec le champ, mais autorise l'évaluation du modèle et renvoie les données à l'appelant. Nous vous recommandons d'utiliser $utils.appendError() lorsque votre application doit renvoyer des résultats partiels.

Enregistrez le résolveur et accédez à la page Requêtes de la AWS AppSync console. Nous allons maintenant envoyer quelques relevés des capteurs.

Exécutez la mutation suivante :

mutation sendReadings { recordReadings( tempReadings: [ {sensorId: 1, value: 85.5, timestamp: "2018-02-01T17:21:05.000+08:00"}, {sensorId: 1, value: 85.7, timestamp: "2018-02-01T17:21:06.000+08:00"}, {sensorId: 1, value: 85.8, timestamp: "2018-02-01T17:21:07.000+08:00"}, {sensorId: 1, value: 84.2, timestamp: "2018-02-01T17:21:08.000+08:00"}, {sensorId: 1, value: 81.5, timestamp: "2018-02-01T17:21:09.000+08:00"} ] locReadings: [ {sensorId: 1, lat: 47.615063, long: -122.333551, timestamp: "2018-02-01T17:21:05.000+08:00"}, {sensorId: 1, lat: 47.615163, long: -122.333552, timestamp: "2018-02-01T17:21:06.000+08:00"} {sensorId: 1, lat: 47.615263, long: -122.333553, timestamp: "2018-02-01T17:21:07.000+08:00"} {sensorId: 1, lat: 47.615363, long: -122.333554, timestamp: "2018-02-01T17:21:08.000+08:00"} {sensorId: 1, lat: 47.615463, long: -122.333555, timestamp: "2018-02-01T17:21:09.000+08:00"} ]) { locationReadings { sensorId timestamp lat long } temperatureReadings { sensorId timestamp value } } }

Nous avons envoyé 10 relevés de capteurs dans une mutation, les relevés étant répartis entre deux tables. Utilisez la console DynamoDB pour vérifier que les données apparaissent à la fois dans les locationReadingstables et. temperatureReadings

BatchDeleteItem - Suppression des relevés du capteur

Nous pouvons aussi avoir besoin de supprimer des lots de relevés de capteurs. Nous allons utiliser le champ GraphQL Mutation.deleteReadings à cet effet. Sélectionnez Attach (Attacher) en regard du champ Mutation.recordReadings. Sur l'écran suivant, sélectionnez la source de données BatchTutorial créée au début du didacticiel.

Utilisons ensuite le modèle de mappage de demande suivant :

Modèle de mappage de demande

## Convert tempReadings arguments to DynamoDB primary keys #set($tempReadings = []) #foreach($reading in ${ctx.args.tempReadings}) #set($pkey = {}) $util.qr($pkey.put("sensorId", $reading.sensorId)) $util.qr($pkey.put("timestamp", $reading.timestamp)) $util.qr($tempReadings.add($util.dynamodb.toMapValues($pkey))) #end ## Convert locReadings arguments to DynamoDB primary keys #set($locReadings = []) #foreach($reading in ${ctx.args.locReadings}) #set($pkey = {}) $util.qr($pkey.put("sensorId", $reading.sensorId)) $util.qr($pkey.put("timestamp", $reading.timestamp)) $util.qr($locReadings.add($util.dynamodb.toMapValues($pkey))) #end { "version" : "2018-05-29", "operation" : "BatchDeleteItem", "tables" : { "locationReadings": $utils.toJson($locReadings), "temperatureReadings": $utils.toJson($tempReadings) } }

Le modèle de mappage de réponse est le même que celui utilisé pour Mutation.recordReadings.

Modèle de mappage de réponse

## If there was an error with the invocation ## there might have been partial results #if($ctx.error) ## Append a GraphQL error for that field in the GraphQL response $utils.appendError($ctx.error.message, $ctx.error.message) #end ## Also return data for the field in the GraphQL response $utils.toJson($ctx.result.data)

Enregistrez le résolveur et accédez à la page Requêtes de la AWS AppSync console. Maintenant, nous allons supprimer un ou deux relevés de capteurs.

Exécutez la mutation suivante :

mutation deleteReadings { # Let's delete the first two readings we recorded deleteReadings( tempReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}] locReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]) { locationReadings { sensorId timestamp lat long } temperatureReadings { sensorId timestamp value } } }

Vérifiez via la console DynamoDB que ces deux lectures ont été supprimées locationReadingsdes tables et. temperatureReadings

BatchGetItem - Récupérez les lectures

Une autre opération courante pour l'application Pet Health consiste à récupérer les relevés d'un capteur à un instant précis. Nous allons joindre un résolveur au champ GraphQL Query.getReadings dans notre schéma. Sélectionnez Attach (Attacher) et, sur l'écran suivant, sélectionnez la source de données BatchTutorial créée au début du didacticiel.

Nous ajoutons ensuite le modèle de mappage de demande suivant :

Modèle de mappage de demande

## Build a single DynamoDB primary key, ## as both locationReadings and tempReadings tables ## share the same primary key structure #set($pkey = {}) $util.qr($pkey.put("sensorId", $ctx.args.sensorId)) $util.qr($pkey.put("timestamp", $ctx.args.timestamp)) { "version" : "2018-05-29", "operation" : "BatchGetItem", "tables" : { "locationReadings": { "keys": [$util.dynamodb.toMapValuesJson($pkey)], "consistentRead": true }, "temperatureReadings": { "keys": [$util.dynamodb.toMapValuesJson($pkey)], "consistentRead": true } } }

Notez que nous utilisons maintenant l'BatchGetItemopération.

Notre modèle de mappage de réponse va être légèrement différent, car nous avons choisi de renvoyer une liste SensorReading. Nous allons mapper le résultat de l'appel au format souhaité.

Modèle de mappage de réponse

## Merge locationReadings and temperatureReadings ## into a single list ## __typename needed as schema uses an interface #set($sensorReadings = []) #foreach($locReading in $ctx.result.data.locationReadings) $util.qr($locReading.put("__typename", "LocationReading")) $util.qr($sensorReadings.add($locReading)) #end #foreach($tempReading in $ctx.result.data.temperatureReadings) $util.qr($tempReading.put("__typename", "TemperatureReading")) $util.qr($sensorReadings.add($tempReading)) #end $util.toJson($sensorReadings)

Enregistrez le résolveur et accédez à la page Requêtes de la AWS AppSync console. Maintenant, nous allons récupérer les relevés des capteurs.

Exécutez la requête suivante :

query getReadingsForSensorAndTime { # Let's retrieve the very first two readings getReadings(sensorId: 1, timestamp: "2018-02-01T17:21:06.000+08:00") { sensorId timestamp ...on TemperatureReading { value } ...on LocationReading { lat long } } }

Nous avons démontré avec succès l'utilisation des opérations par lots DynamoDB à l'aide de. AWS AppSync

Gestion des erreurs

Dans AWS AppSync, les opérations de source de données peuvent parfois renvoyer des résultats partiels. Le terme résultats partiels est le terme que nous allons utiliser pour désigner une sortie d'opération composée de données et d'une erreur. La gestion des erreurs étant intrinsèquement spécifique à l'application, AWS AppSync vous avez la possibilité de gérer les erreurs dans le modèle de mappage des réponses. L'erreur d'appel du résolveur, le cas échéant, est disponible depuis le contexte sous la forme $ctx.error. Les erreurs d'appel incluent toujours un message et un type, accessibles sous la forme des propriétés $ctx.error.message et $ctx.error.type. Pendant l'appel du modèle de mappage de réponse, vous pouvez gérer les résultats partiels de trois manières :

  1. Par la digestion de l'erreur d'appel en renvoyant simplement les données.

  2. Par le déclenchement d'une erreur (en utilisant $util.error(...)) en arrêtant l'évaluation du modèle de mappage de réponse, qui ne renvoie alors aucune donnée.

  3. Par l'ajout d'une erreur (en utilisant $util.appendError(...)) tout en renvoyant les données.

Nous allons présenter chacun des trois points ci-dessus avec les opérations par lots DynamoDB.

Opérations par lots DynamoDB

Dans le cas des opérations par lots DynamoDB, il est possible qu'un lot ne soit exécuté que partiellement. En d'autres termes, il est possible que certains des éléments ou des clés demandés ne soient pas traités. S'il n' AWS AppSync est pas possible de terminer un lot, les éléments non traités et une erreur d'invocation seront définis dans le contexte.

Nous allons mettre en œuvre la gestion des erreurs à l'aide de la configuration de champ Query.getReadings de l'opération BatchGetItem provenant de la section précédente de ce didacticiel. Cette fois, nous allons supposer que, lors de l'exécution du champ Query.getReadings, la table DynamoDB temperatureReadings a dépassé le débit alloué. DynamoDB a généré ProvisionedThroughputExceededExceptionun à la deuxième tentative pour traiter AWS AppSync les éléments restants du lot.

Ce qui suit JSON représente le contexte sérialisé après l'appel par lots de DynamoDB mais avant l'évaluation du modèle de mappage des réponses.

{ "arguments": { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" }, "source": null, "result": { "data": { "temperatureReadings": [ null ], "locationReadings": [ { "lat": 47.615063, "long": -122.333551, "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ] }, "unprocessedKeys": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] } }, "error": { "type": "DynamoDB:ProvisionedThroughputExceededException", "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" }, "outErrors": [] }

Quelques points à noter concernant le contexte :

  • l'erreur d'appel a été définie sur le contexte à $ctx.error by AWS AppSync, et le type d'erreur a été défini sur DynamoDB :. ProvisionedThroughputExceededException

  • Les résultats sont mappés par table sous $ctx.result.data, même si une erreur est présente.

  • Les clés qui n'ont pas été traitées sont disponibles à l'adresse $ctx.result.data.unprocessedKeys. Ici, AWS AppSync impossible de récupérer l'élément avec la clé (:1sensorId, Timestamp:2018-02-01T 17:21:05.000 + 08:00) en raison d'un débit de table insuffisant.

Remarque : Pour BatchPutItem, la valeur est $ctx.result.data.unprocessedItems. Pour BatchDeleteItem, la valeur est $ctx.result.data.unprocessedKeys.

Nous allons traiter cette erreur de trois façons différentes.

1. Digestion de l'erreur d'appel

Le renvoi des données sans gestion de l'erreur d'appel se traduit par une digestion de l'erreur, ce qui permet au résultat du champ GraphQL donné d'être toujours réussi.

Le modèle de mappage de réponse que nous écrivons est courant et ne se concentre que sur les données de résultat.

Modèle de mappage de réponse :

$util.toJson($ctx.result.data)

Réponse GraphQL :

{ "data": { "getReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "lat": 47.615063, "long": -122.333551 }, { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "value": 85.5 } ] } }

Aucune erreur n'est ajoutée à la réponse d'erreur car l'action n'a porté que sur les données.

2. Déclenchement d'une erreur pour interrompre l'exécution du modèle

Lorsque les défaillances partielles doivent être traitées comme des défaillances complètes du point de vue du client, vous pouvez abandonner l'exécution du modèle pour empêcher le renvoi des données. La méthode d'utilitaire $util.error(...) permet d'obtenir exactement ce comportement.

Modèle de mappage de réponse :

## there was an error let's mark the entire field ## as failed and do not return any data back in the response #if ($ctx.error) $util.error($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys) #end $util.toJson($ctx.result.data)

Réponse GraphQL :

{ "data": { "getReadings": null }, "errors": [ { "path": [ "getReadings" ], "data": null, "errorType": "DynamoDB:ProvisionedThroughputExceededException", "errorInfo": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] }, "locations": [ { "line": 58, "column": 3 } ], "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" } ] }

Même si certains résultats peuvent avoir été renvoyés par l'opération de traitement par lots DynamoDB, nous avons choisi de déclencher une erreur se traduisant par une valeur null pour le champ GraphQL getReadings et l'erreur a été ajoutée au bloc d'erreurs de la réponse GraphQL.

3. Ajout d'une erreur pour renvoyer à la fois les données et les erreurs

Dans certains cas, afin d'offrir une meilleure expérience utilisateur, les applications peuvent renvoyer des résultats partiels et informer leurs clients des éléments non traités. Les clients peuvent choisir d'implémenter une nouvelle tentative ou de renvoyer l'erreur à l'utilisateur final. C'est la méthode d'utilitaire $util.appendError(...) qui permet d'obtenir ce comportement en laissant le concepteur de l'application ajouter les erreurs au contexte sans interférer avec l'évaluation du modèle. Après avoir évalué le modèle, AWS AppSync traitera toutes les erreurs de contexte en les ajoutant au bloc d'erreurs de la réponse GraphQL.

Modèle de mappage de réponse :

#if ($ctx.error) ## pass the unprocessed keys back to the caller via the `errorInfo` field $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys) #end $util.toJson($ctx.result.data)

Nous avons transmis à la fois l'erreur d'invocation et l' unprocessedKeys élément contenu dans le bloc d'erreurs de la réponse GraphQL. Le getReadings champ renvoie également des données partielles de la locationReadingstable, comme vous pouvez le voir dans la réponse ci-dessous.

Réponse GraphQL :

{ "data": { "getReadings": [ null, { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "value": 85.5 } ] }, "errors": [ { "path": [ "getReadings" ], "data": null, "errorType": "DynamoDB:ProvisionedThroughputExceededException", "errorInfo": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] }, "locations": [ { "line": 58, "column": 3 } ], "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" } ] }