Referencia de plantillas de mapeo de solucionador para Lambda - AWS AppSync

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Referencia de plantillas de mapeo de solucionador para Lambda

nota

Ahora admitimos de forma básica el tiempo de ejecución APPSYNC_JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC_JS y sus guías aquí.

Puede usar las plantillas de mapeo de solucionador de AWS AppSync para AWS Lambda para dar forma a las peticiones de AWS AppSync dirigidas a las funciones de Lambda ubicadas en su cuenta y también a las respuestas de estas hacia AWS AppSync. También puede usar las plantillas de mapeo para indicar a AWS AppSync la naturaleza de la operación que se va a invocar. En esta sección se describen las distintas plantillas de mapeo para las operaciones de Lambda admitidas.

Plantilla de mapeo de solicitudes

La plantilla de mapeo de solicitud Lambda es bastante sencilla y permite transferir toda la información de contexto posible a la función Lambda.

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

A continuación, se muestra el esquema JSON de la plantilla de mapeo de la solicitud Lambda una vez resuelta.

{ "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": {} }, "required": [ "version", "operation" ], "additionalProperties": false }

En el ejemplo siguiente hemos transferido el valor field y los argumentos de campo de GraphQL desde el contexto.

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

Todo el documento de mapeo se transfiere como entrada a la función de Lambda, de modo que el ejemplo anterior tendría el siguiente aspecto:

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

Versión

version es común a todas las plantillas de mapeo de solicitud y define la versión utilizada por la plantilla. version es obligatorio.

"version": "2018-05-29"

Operación

El origen de datos de Lambda permite definir dos operaciones: Invoke y BatchInvoke. La operación Invoke hace que AWS AppSync llame a la función de Lambda para cada solucionador de campo de GraphQL. BatchInvoke indica a AWS AppSync que realice solicitudes en lotes para el campo de GraphQL actual.

operation es obligatorio.

Para Invoke, la plantilla de mapeo de solicitudes resuelta coincide exactamente con la carga de entrada de la función de Lambda. De este modo, la plantilla de ejemplo siguiente:

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

se resuelve y se transfiere a la función Lambda como se indica a continuación:

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

Para BatchInvoke, la plantilla de mapeo se aplica para cada solucionador de campo del lote. Por motivos de concisión, AWS AppSync combina todos los valores payload de la plantilla de mapeo resuelta en una lista bajo un solo objeto que coincide con la plantilla de mapeo.

La siguiente plantilla de ejemplo muestra esta combinación:

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

Esta plantilla se resuelve para dar el siguiente documento de mapeo:

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

donde cada elemento de la lista payload se corresponde con cada elemento del lote. También se espera que la función Lambda devuelva una respuesta en forma de lista, que coincida con el orden de los elementos enviados en la solicitud, tal y como se indica a continuación:

[ { "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 ]

operation es obligatorio.

Carga

El campo payload es un contenedor que puede utilizar para transferir cualquier formato JSON correcto a la función Lambda.

Si el campo operation se establece en BatchInvoke, AWS AppSync agrupará los valores payload existentes en una lista.

payload es opcional.

Plantilla de mapeo de respuestas

Al igual que ocurre con otros orígenes de datos, la función de Lambda envía una respuesta a AWS AppSync que debe convertirse en un tipo de GraphQL.

El resultado de la función de Lambda se define con el objeto context que está disponible a través de la propiedad $context.result de Velocity Template Language (VTL).

Si la forma de la respuesta de la función Lambda coincide exactamente con la forma del tipo de GraphQL, puede reenviar la respuesta mediante la siguiente plantilla de mapeo de respuesta:

$util.toJson($context.result)

No hay campos obligatorios ni restricciones de forma aplicables a la plantilla de mapeo de respuesta. Sin embargo, dado que los tipos de GraphQL son estrictos, la plantilla de mapeo resuelta debe coincidir con el tipo de GraphQL previsto.

Repuesta de la función de Lambda en lotes

Si el campo operation se establece en BatchInvoke, AWS AppSync espera que la función de Lambda devuelva una lista de elementos. Para que AWS AppSync pueda mapear cada resultado a cada elemento de la solicitud original, la lista de respuestas debe coincidir en tamaño y orden. La lista de respuestas puede incluir elementos null. $ctx.result se establece en null en consecuencia.

Solucionadores de Lambda directos

Si desea eludir por completo el uso de plantillas de mapeo, AWS AppSync puede proporcionar una carga útil predeterminada a la función de Lambda y un valor predeterminado de la respuesta de una función de Lambda a un tipo de GraphQL. Puede optar por proporcionar una plantilla de solicitud, una plantilla de respuesta o ninguna de las dos, y AWS AppSync se ocupará de su gestión en consecuencia.

Plantilla de mapeo de la solicitud Lambda directa

Si no se proporciona la plantilla de mapeo de solicitudes, AWS AppSync enviará el objeto Context directamente a la función de Lambda como una operación Invoke. Para obtener más información sobre la estructura del objeto Context, consulte Referencia de contexto de las plantillas de mapeo del solucionador.

Plantilla de mapeo de la respuesta de Lambda directa

Si no se proporciona la plantilla de mapeo de respuestas, AWS AppSync realizará una de estas dos acciones al recibir la respuesta de la función de Lambda. Si no ha proporcionado una plantilla de mapeo de solicitudes o si ha proporcionado una plantilla de mapeo de solicitudes con la versión "2018-05-29", la lógica de respuesta funciona de manera equivalente a la siguiente plantilla de mapeo de respuestas:

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

Si ha proporcionado una plantilla con la versión "2017-02-28", la lógica de respuesta funciona de manera equivalente a la siguiente plantilla de mapeo de respuestas:

$util.toJson($ctx.result)

Superficialmente, la omisión de plantillas de mapeo funciona de manera similar a utilizar ciertas plantillas de mapeo, como se muestra en los ejemplos anteriores. Sin embargo, entre bastidores, se elude por completo la evaluación de las plantillas de mapeo. Al omitirse el paso de evaluación de la plantilla, en algunos escenarios las aplicaciones pueden experimentar menos sobrecarga y latencia durante la respuesta en comparación con una función de Lambda con una plantilla de mapeo de respuestas que debe evaluarse.

Gestión de errores personalizada en las respuestas de solucionador de Lambda directo

Puede personalizar las respuestas de error de las funciones de Lambda que invocan los solucionadores de Lambda directos mostrando una excepción personalizada. En el siguiente ejemplo se muestra cómo crear una excepción personalizada mediante JavaScript:

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

Cuando se muestran excepciones, errorType y errorMessage son el name y message, respectivamente, del error personalizado que se produce.

Si errorType es UnauthorizedException, AWS AppSync devuelve el mensaje predeterminado ("You are not authorized to make this call.") en lugar de uno personalizado.

A continuación, tenemos un ejemplo de la respuesta de GraphQL que muestra un errorType personalizado.

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

Solucionadores de Lambda directos: agrupación en lotes habilitada

Puede habilitar la agrupación en lotes para el solucionador de Lambda directo mediante la configuración del maxBatchSize en el solucionador. Cuando maxBatchSize se establece en un valor superior a 0 para un solucionador de Lambda directo, AWS AppSync envía solicitudes en lotes a la función de Lambda en tamaños de hasta maxBatchSize.

Si maxBatchSize se establece en 0 en un solucionador de Lambda directo, se desactiva la agrupación en lotes.

Para obtener más información sobre el funcionamiento de la agrupación en lotes con solucionadores de Lambda, consulte Caso de uso avanzado: agrupación en lotes.

Plantilla de mapeo de solicitudes

Si la agrupación en lotes está habilitada y no se proporciona la plantilla de mapeo de solicitudes, AWS AppSync envía una lista de objetos Context como una operación BatchInvoke directamente a la función de Lambda.

Plantilla de mapeo de respuestas

Si la agrupación en lotes está habilitada y no se proporciona la plantilla de mapeo de respuestas, la lógica de respuesta es equivalente a la siguiente plantilla de mapeo de respuestas:

#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 función de Lambda debe devolver una lista de resultados en el mismo orden que la lista de objetos Context que se han enviado. Puede devolver errores individuales proporcionando un errorMessage y errorType para un resultado específico. Cada resultado de la lista se indica con el formato siguiente:

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

Actualmente, se ignoran otros campos del objeto de resultado.

Gestión de errores de Lambda

Puede devolver un error para todos los resultados produciendo una excepción o un error en la función de Lambda. Si el tamaño de respuesta o solicitud de carga de la solicitud por lote es demasiado grande, Lambda devolverá un error. En ese caso, debería considerar la posibilidad de reducir el maxBatchSize o el tamaño de la carga de la respuesta.

Para obtener información sobre la gestión de errores individuales, consulte Devolución de errores individuales.

Funciones de Lambda de ejemplo

Con el siguiente esquema, puede crear un solucionador de Lambda directo para el solucionador de campo Post.relatedPosts y habilitar la agrupación en lotes estableciendo maxBatchSize en mayor que 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] }

En la siguiente consulta, se llamará a la función de Lambda con lotes de solicitudes para resolver relatedPosts:

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

A continuación, se proporciona una implementación sencilla de una función de Lambda:

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