Référence du modèle de mappage Resolver pour Lambda - 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.

Référence du modèle de mappage Resolver pour Lambda

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.

Vous pouvez utiliser des AWS AppSync fonctions et des résolveurs pour appeler les fonctions Lambda situées dans votre compte. Vous pouvez façonner les charges utiles de vos demandes et la réponse de vos fonctions Lambda avant de les renvoyer à vos clients. Vous pouvez également utiliser des modèles de mappage pour donner des indications AWS AppSync sur la nature de l'opération à invoquer. Cette section décrit les différents modèles de mappage pour les opérations Lambda prises en charge.

Modèle de mappage des demandes

Le modèle de mappage de requêtes Lambda gère les champs liés à votre fonction Lambda :

{ "version": string, "operation": Invoke|BatchInvoke, "payload": any type, "invocationType": RequestResponse|Event }

Voici la représentation du schéma JSON du modèle de mappage de demandes Lambda une fois résolu :

{ "definitions": {}, "$schema": "https://json-schema.org/draft-06/schema#", "$id": "https://aws.amazon.com/appsync/request-mapping-template.json", "type": "object", "properties": { "version": { "$id": "/properties/version", "type": "string", "enum": [ "2018-05-29" ], "title": "The Mapping template version.", "default": "2018-05-29" }, "operation": { "$id": "/properties/operation", "type": "string", "enum": [ "Invoke", "BatchInvoke" ], "title": "The Mapping template operation.", "description": "What operation to execute.", "default": "Invoke" }, "payload": {}, "invocationType": { "$id": "/properties/invocationType", "type": "string", "enum": [ "RequestResponse", "Event" ], "title": "The Mapping template invocation type.", "description": "What invocation type to execute.", "default": "RequestResponse" } }, "required": [ "version", "operation" ], "additionalProperties": false }

Voici un exemple qui utilise une invoke opération dont les données de charge utile sont le getPost champ d'un schéma GraphQL avec ses arguments issus du contexte :

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "field": "getPost", "arguments": $util.toJson($context.arguments) } }

L'intégralité du document de mappage est transmise en entrée à votre fonction Lambda, de sorte que l'exemple précédent ressemble désormais à ceci :

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "field": "getPost", "arguments": { "id": "postId1" } } }

Version

Commun à tous les modèles de mappage de demandes, il version définit la version utilisée par le modèle. Le version est obligatoire et est une valeur statique :

"version": "2018-05-29"

Opération

La source de données Lambda vous permet de définir deux opérations operation sur le terrain : Invoke et. BatchInvoke L'Invokeopération permet de AWS AppSync savoir d'appeler votre fonction Lambda pour chaque résolveur de champs GraphQL. BatchInvokeindique de regrouper AWS AppSync les requêtes pour le champ GraphQL actuel. Le champ operation est obligatoire.

En effetInvoke, le modèle de mappage des demandes résolues correspond à la charge utile d'entrée de la fonction Lambda. Modifions l'exemple ci-dessus :

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "arguments": $util.toJson($context.arguments) } }

Ceci est résolu et transmis à la fonction Lambda, qui pourrait ressembler à ceci :

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "arguments": { "id": "postId1" } } }

En BatchInvoke effet, le modèle de mappage est appliqué à chaque résolveur de champs du lot. Par souci de concision, AWS AppSync fusionne toutes les payload valeurs du modèle de mappage résolues dans une liste sous un seul objet correspondant au modèle de mappage. Le modèle d'exemple suivant affiche la fusion :

{ "version": "2018-05-29", "operation": "BatchInvoke", "payload": $util.toJson($context) }

Ce modèle est résolu dans le document de mappage suivant :

{ "version": "2018-05-29", "operation": "BatchInvoke", "payload": [ {...}, // context for batch item 1 {...}, // context for batch item 2 {...} // context for batch item 3 ] }

Chaque élément de la payload liste correspond à un seul article du lot. La fonction Lambda devrait également renvoyer une réponse sous forme de liste correspondant à l'ordre des éléments envoyés dans la demande :

[ { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1 { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2 { "data": {...}, "errorMessage": null, "errorType": null } // result for batch item 3 ]

Charge utile

Le payload champ est un conteneur utilisé pour transmettre n'importe quel JSON bien formé à la fonction Lambda. Si le operation champ est défini surBatchInvoke, AWS AppSync regroupe les payload valeurs existantes dans une liste. Le champ payload est facultatif.

Type d'invocation

La source de données Lambda vous permet de définir deux types d'invocation : et. RequestResponse Event Les types d'invocation sont synonymes des types d'invocation définis dans l'API Lambda. Le type RequestResponse d'invocation permet d' AWS AppSync appeler votre fonction Lambda de manière synchrone pour attendre une réponse. L'Eventinvocation vous permet d'appeler votre fonction Lambda de manière asynchrone. Pour plus d'informations sur la façon dont Lambda gère les demandes de type Event invocation, consultez Invocation asynchrone. Le champ invocationType est facultatif. Si ce champ n'est pas inclus dans la demande, le type d'RequestResponseappel AWS AppSync sera défini par défaut.

Quel que soit invocationType le champ, la demande résolue correspond à la charge utile d'entrée de la fonction Lambda. Modifions l'exemple ci-dessus :

{ "version": "2018-05-29", "operation": "Invoke", "invocationType": "Event" "payload": { "arguments": $util.toJson($context.arguments) } }

Ceci est résolu et transmis à la fonction Lambda, qui pourrait ressembler à ceci :

{ "version": "2018-05-29", "operation": "Invoke", "invocationType": "Event", "payload": { "arguments": { "id": "postId1" } } }

Lorsque l'BatchInvokeopération est utilisée conjointement avec le champ de type d'Eventappel, elle AWS AppSync fusionne le résolveur de champ de la même manière que celle mentionnée ci-dessus, et la demande est transmise à votre fonction Lambda sous forme d'événement asynchrone sous la forme d'une liste de valeurs. payload Nous vous recommandons de désactiver la mise en cache des résolveurs pour les résolveurs de type Event invocation, car ceux-ci ne seraient pas envoyés à Lambda en cas d'accès au cache.

Modèle de mappage des réponses

Comme pour les autres sources de données, votre fonction Lambda envoie une réponse AWS AppSync qui doit être convertie en un type GraphQL.

Le résultat de la fonction Lambda est défini sur l'contextobjet disponible via la propriété Velocity Template Language (VTL). $context.result

Si la forme de la réponse de la fonction Lambda correspond exactement à celle du type GraphQL, vous pouvez transmettre la réponse à l'aide du modèle de mappage de réponse suivant :

$util.toJson($context.result)

Il n'y a pas de champs obligatoires ni de restrictions des formes qui s'appliquent au modèle de mappage de la réponse. Toutefois, dans la mesure où GraphQL est fortement typé, le modèle de mappage résolu doit correspondre au type GraphQL prévu.

Réponse par lots de la fonction Lambda

Si le operation champ est défini surBatchInvoke, AWS AppSync attend une liste d'éléments en retour de la fonction Lambda. Afin de AWS AppSync faire correspondre chaque résultat à l'élément de demande d'origine, la liste de réponses doit correspondre en taille et en ordre. Il est valide d'avoir des null éléments dans la liste de réponses ; elle $ctx.result est définie sur null en conséquence.

Résolveurs Lambda directs

Si vous souhaitez éviter complètement l'utilisation de modèles de mappage, vous AWS AppSync pouvez fournir une charge utile par défaut à votre fonction Lambda et une réponse de fonction Lambda par défaut à un type GraphQL. Vous pouvez choisir de fournir un modèle de demande, un modèle de réponse ou aucun des deux, et AWS AppSync le gérer en conséquence.

Modèle de mappage de requêtes Lambda direct

Lorsque le modèle de mappage de demandes n'est pas fourni, l'Contextobjet AWS AppSync sera envoyé directement à votre fonction Lambda sous forme d'Invokeopération. Pour plus d'informations sur la structure de l'objet Context, consultez Référence contextuelle du modèle de mappage Resolver.

Modèle de mappage des réponses Lambda directes

Lorsque le modèle de mappage des réponses n'est pas fourni, AWS AppSync effectuez l'une des deux opérations suivantes après avoir reçu la réponse de votre fonction Lambda. Si vous n'avez pas fourni de modèle de mappage de demandes ou si vous avez fourni un modèle de mappage de demandes avec la version2018-05-29, la réponse sera équivalente au modèle de mappage de réponse suivant :

#if($ctx.error) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #end $util.toJson($ctx.result)

Si vous avez fourni un modèle avec la version2017-02-28, la logique de réponse fonctionne de la même manière que le modèle de mappage des réponses suivant :

$util.toJson($ctx.result)

À première vue, le contournement du modèle de mappage fonctionne de la même manière que l'utilisation de certains modèles de mappage, comme indiqué dans les exemples précédents. Cependant, dans les coulisses, l'évaluation des modèles de mappage est totalement contournée. Dans la mesure où l'étape d'évaluation du modèle est contournée, les applications peuvent être confrontées à moins de surcharge et de latence pendant la réponse dans certains scénarios par rapport à une fonction Lambda avec un modèle de mappage des réponses qui doit être évalué.

Gestion personnalisée des erreurs dans les réponses Direct Lambda Resolver

Vous pouvez personnaliser les réponses aux erreurs issues des fonctions Lambda invoquées par les résolveurs Lambda directs en déclenchant une exception personnalisée. L'exemple suivant montre comment créer une exception personnalisée en utilisant JavaScript :

class CustomException extends Error { constructor(message) { super(message); this.name = "CustomException"; } } throw new CustomException("Custom message");

Lorsque des exceptions sont déclenchées, les errorType name et errorMessage message sont respectivement les et et de l'erreur personnalisée générée.

Dans errorType l'affirmativeUnauthorizedException, AWS AppSync renvoie le message par défaut ("You are not authorized to make this call.") au lieu d'un message personnalisé.

L'extrait suivant est un exemple de réponse GraphQL illustrant une personnalisation : errorType

{ "data": { "query": null }, "errors": [ { "path": [ "query" ], "data": null, "errorType": "CustomException", "errorInfo": null, "locations": [ { "line": 5, "column": 10, "sourceName": null } ], "message": "Custom Message" } ] }

Résolveurs Lambda directs : le traitement par lots est activé

Vous pouvez activer le traitement par lots pour votre résolveur Lambda direct en le maxBatchSize configurant sur votre résolveur. Lorsqu'il maxBatchSize est défini sur une valeur supérieure à celle 0 d'un résolveur Lambda direct, il AWS AppSync envoie des requêtes par lots à votre fonction Lambda dans des tailles allant jusqu'à. maxBatchSize

Le réglage maxBatchSize 0 sur sur un résolveur Direct Lambda désactive le traitement par lots.

Pour plus d'informations sur le fonctionnement du traitement par lots avec des résolveurs Lambda, consultez. Cas d'utilisation avancé : traitement par lots

Modèle de mappage des demandes

Lorsque le traitement par lots est activé et que le modèle de mappage des demandes n'est pas fourni, AWS AppSync envoie une liste d'Contextobjets sous forme d'BatchInvokeopération directement à votre fonction Lambda.

Modèle de mappage des réponses

Lorsque le traitement par lots est activé et que le modèle de mappage des réponses n'est pas fourni, la logique de réponse est équivalente au modèle de mappage des réponses suivant :

#if( $context.result && $context.result.errorMessage ) $utils.error($context.result.errorMessage, $context.result.errorType, $context.result.data) #else $utils.toJson($context.result.data) #end

La fonction Lambda doit renvoyer une liste de résultats dans le même ordre que la liste des Context objets envoyés. Vous pouvez renvoyer des erreurs individuelles en fournissant un errorMessage et errorType pour un résultat spécifique. Chaque résultat de la liste a le format suivant :

{ "data" : { ... }, // your data "errorMessage" : { ... }, // optional, if included an error entry is added to the "errors" object in the AppSync response "errorType" : { ... } // optional, the error type }
Note

Les autres champs de l'objet de résultat sont actuellement ignorés.

Gestion des erreurs liées à Lambda

Vous pouvez renvoyer une erreur pour tous les résultats en lançant une exception ou une erreur dans votre fonction Lambda. Si la taille de la demande de charge utile ou de réponse pour votre demande de lot est trop importante, Lambda renvoie une erreur. Dans ce cas, vous devez envisager de réduire votre charge utile de réponse maxBatchSize ou de réduire sa taille.

Pour plus d'informations sur la gestion des erreurs individuelles, voirRenvoi d'erreurs individuelles.

Exemples de fonctions Lambda

À l'aide du schéma ci-dessous, vous pouvez créer un résolveur Lambda direct pour le résolveur de Post.relatedPosts champs et activer le traitement par lots en définissant les paramètres ci-dessus : maxBatchSize 0

schema { query: Query mutation: Mutation } type Query { getPost(id:ID!): Post allPosts: [Post] } type Mutation { addPost(id: ID!, author: String!, title: String, content: String, url: String): Post! } type Post { id: ID! author: String! title: String content: String url: String ups: Int downs: Int relatedPosts: [Post] }

Dans la requête suivante, la fonction Lambda sera appelée avec des lots de demandes à résoudre : relatedPosts

query getAllPosts { allPosts { id relatedPosts { id } } }

Une implémentation simple d'une fonction Lambda est fournie ci-dessous :

const posts = { 1: { id: '1', title: 'First book', author: 'Author1', url: 'https://amazon.com/', content: 'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1', ups: '100', downs: '10', }, 2: { id: '2', title: 'Second book', author: 'Author2', url: 'https://amazon.com', content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT', ups: '100', downs: '10', }, 3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null }, 4: { id: '4', title: 'Fourth book', author: 'Author4', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4', ups: '1000', downs: '0', }, 5: { id: '5', title: 'Fifth book', author: 'Author5', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT', ups: '50', downs: '0', }, } const relatedPosts = { 1: [posts['4']], 2: [posts['3'], posts['5']], 3: [posts['2'], posts['1']], 4: [posts['2'], posts['1']], 5: [], } exports.handler = async (event) => { console.log('event ->', event) // retrieve the ID of each post const ids = event.map((context) => context.source.id) // fetch the related posts for each post id const related = ids.map((id) => relatedPosts[id]) // return the related posts; or an error if none were found return related.map((r) => { if (r.length > 0) { return { data: r } } else { return { data: null, errorMessage: 'Not found', errorType: 'ERROR' } } }) }