

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# AWS AppSync referência de modelo de mapeamento de resolvedor para Lambda
<a name="resolver-mapping-template-reference-lambda"></a>

**nota**  
Agora, oferecemos suporte principalmente ao runtime do APPSYNC\$1JS e sua documentação. Considere usar o runtime do APPSYNC\$1JS e seus guias disponíveis [aqui](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

Você pode usar AWS AppSync funções e resolvedores para invocar funções do Lambda localizadas em sua conta. Você pode moldar suas cargas úteis de solicitação e a resposta de suas funções do Lambda antes de devolvê-las aos seus clientes. Você também pode usar modelos de mapeamento para dar dicas AWS AppSync sobre a natureza da operação a ser invocada. Esta seção descreve os diferentes modelos de mapeamento para as operações do Lambda compatíveis.

## Modelo de mapeamento de solicitações
<a name="request-mapping-template"></a>

O modelo de mapeamento de solicitações do Lambda manipula campos relacionados à sua função do Lambda:

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

Esta é a representação do esquema JSON do modelo de mapeamento de solicitações do Lambda quando resolvido:

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

Aqui está um exemplo que usa uma operação `invoke` com seus dados de carga útil sendo o campo `getPost` de um esquema GraphQL junto com seus argumentos do contexto:

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

Todo o documento de mapeamento é passado como entrada para sua função do Lambda; assim, o exemplo anterior agora tem esta aparência:

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

### Versão
<a name="version"></a>

Comum a todos os modelos de mapeamento de solicitação, `version` define a versão usada pelo modelo. O `version` é obrigatório e é um valor estático:

```
"version": "2018-05-29"
```

### Operation
<a name="operation"></a>

A fonte de dados do Lambda permite que você defina duas operações no campo `operation`: `Invoke` e `BatchInvoke`. A `Invoke` operação permite AWS AppSync que você chame sua função Lambda para cada resolvedor de campo do GraphQL. `BatchInvoke`instrui as solicitações em lote AWS AppSync para o campo GraphQL atual. O campo `operation` é obrigatório.

Para `Invoke`, o modelo de mapeamento da solicitação resolvido corresponde à carga útil de entrada da função do Lambda. Vamos modificar o exemplo acima:

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

Isso é resolvido e passado para a função do Lambda, que poderá ser mais ou menos assim:

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

Para `BatchInvoke`, o modelo de mapeamento é aplicado a cada resolvedor do campo no lote. Para ser conciso, AWS AppSync mescla todos os `payload` valores do modelo de mapeamento resolvido em uma lista sob um único objeto correspondente ao modelo de mapeamento. O exemplo de modelo a seguir mostra a mesclagem:

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

Esse modelo é resolvido para o seguinte documento de mapeamento:

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

Cada elemento da lista `payload` corresponde a um único item de lote. Também se espera que a função do Lambda retorne uma resposta em forma de lista correspondente à ordem dos itens enviados na solicitação:

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

### Carga útil
<a name="payload"></a>

O campo `payload` é um contêiner usado para passar qualquer JSON bem formado para a função do Lambda. Se o `operation` campo estiver definido como`BatchInvoke`, AWS AppSync agrupa os `payload` valores existentes em uma lista. O campo `payload` é opcional.

### Tipo de invocação
<a name="async-invocation-type"></a>

A fonte de dados do Lambda permite que você defina dois tipos de invocação: `RequestResponse` e `Event`. Os tipos de invocação são sinônimos dos tipos de invocação definidos na [API do Lambda](https://docs.aws.amazon.com//lambda/latest/api/API_Invoke.html). O tipo de `RequestResponse` invocação permite AWS AppSync chamar sua função Lambda de forma síncrona para aguardar uma resposta. A invocação `Event` permite que você invoque sua função do Lambda de forma assíncrona. Para obter mais informações sobre como o Lambda lida com solicitações de tipo de invocação `Event`, consulte [Invocação assíncrona](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html). O campo `invocationType` é opcional. Se esse campo não for incluído na solicitação, o padrão AWS AppSync será o tipo de `RequestResponse` invocação.

Para qualquer campo `invocationType`, a solicitação resolvida corresponde à carga útil de entrada da função do Lambda. Vamos modificar o exemplo acima:

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

Isso é resolvido e passado para a função do Lambda, que poderá ser mais ou menos assim:

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

Quando a `BatchInvoke` operação é usada em conjunto com o campo do tipo de `Event` invocação, AWS AppSync mescla o resolvedor de campo da mesma forma mencionada acima, e a solicitação é passada para sua função Lambda como um evento assíncrono, sendo uma lista de valores. `payload` Recomendamos que você desative o cache do resolvedor para resolvedores do tipo de invocação `Event`, pois eles não seriam enviados ao Lambda se houvesse um acerto do cache.

## Modelo de mapeamento de respostas
<a name="response-mapping-template"></a>

Assim como em outras fontes de dados, sua função Lambda envia uma resposta AWS AppSync que deve ser convertida em um tipo GraphQL.

O resultado da função do Lambda será definido no objeto `context` que está disponível por meio da propriedade `$context.result` do Velocity Template Language (VTL).

Se a forma da resposta da função do Lambda corresponder exatamente à forma do tipo do GraphQL, você pode encaminhar a resposta usando o seguinte modelo de mapeamento da resposta:

```
$util.toJson($context.result)
```

Não existem campos obrigatórios ou restrições de forma que se aplicam ao modelo de mapeamento da resposta. No entanto, como o GraphQL tem vários tipos, o modelo de mapeamento resolvido deve corresponder ao tipo do GraphQL esperado.

## Resposta em lote da função do Lambda
<a name="aws-appsync-resolver-mapping-template-reference-lambda-batched-response"></a>

Se o campo `operation` estiver definido como `BatchInvoke`, o AWS AppSync espera de volta uma lista de itens da função do Lambda. Para AWS AppSync mapear cada resultado de volta ao item da solicitação original, a lista de respostas deve corresponder em tamanho e ordem. É válido ter itens `null` na lista de respostas; `$ctx.result` será adequadamente definido como *nulo*.

## Resolvedores diretos do Lambda
<a name="direct-lambda-resolvers"></a>

Se você quiser contornar totalmente o uso de modelos de mapeamento, AWS AppSync pode fornecer uma carga padrão para sua função Lambda e uma resposta padrão da função Lambda para um tipo GraphQL. Você pode optar por fornecer um modelo de solicitação, um modelo de resposta ou nenhum dos dois e AWS AppSync tratá-los adequadamente.

### Modelo de mapeamento da solicitação direta do Lambda
<a name="lambda-mapping-template-bypass-request"></a>

Quando o modelo de mapeamento da solicitação não for fornecido, AWS AppSync enviará o `Context` objeto diretamente para sua função Lambda como uma `Invoke` operação. Para obter mais informações sobre a estrutura do código-fonte do objeto `Context`, consulte [AWS AppSync referência de contexto do modelo de mapeamento do resolvedor](resolver-context-reference.md).

### Modelo de mapeamento da resposta direta do Lambda
<a name="lambda-mapping-template-bypass-response"></a>

Quando o modelo de mapeamento de resposta não é fornecido, AWS AppSync faz uma das duas coisas ao receber a resposta da função Lambda. Se você não forneceu um modelo de mapeamento de solicitação ou forneceu um modelo de mapeamento de solicitação com a versão `2018-05-29`, a resposta será equivalente ao seguinte modelo de mapeamento de resposta:

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

Se você forneceu um modelo com a versão `2017-02-28`, a lógica de resposta funcionará de forma equivalente ao seguinte modelo de mapeamento de resposta:

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

Superficialmente, o desvio do modelo de mapeamento opera de forma semelhante ao uso de determinados modelos de mapeamento, conforme mostrado nos exemplos anteriores. No entanto, nos bastidores, a avaliação dos modelos de mapeamento é totalmente contornada. Como a etapa de avaliação do modelo é ignorada, em alguns cenários, as aplicações podem ter menos sobrecarga e latência durante a resposta em relação a uma função do Lambda com um modelo de mapeamento de resposta que precisa ser avaliado. 

### Tratamento personalizado de erros nas respostas do resolvedor direto do Lambda
<a name="lambda-mapping-template-bypass-errors"></a>

Você pode personalizar as respostas de erro das funções do Lambda que os resolvedores diretos do Lambda invocam gerando uma exceção personalizada. O exemplo a seguir demonstra como criar uma exceção personalizada usando JavaScript:

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

Quando exceções são geradas, `errorType` e `errorMessage` é `name` e`message`, respectivamente, do erro personalizado que é gerado.

Se `errorType` estiver`UnauthorizedException`, AWS AppSync retorna a mensagem padrão (`"You are not authorized to make this call."`) em vez de uma mensagem personalizada.

Este é um exemplo de resposta do GraphQL que demonstra um `errorType` personalizado:

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

### Resolvedores diretos do Lambda: agrupamento em lotes ativado
<a name="lambda-resolvers-batching"></a>

Você pode habilitar o agrupamento em lotes para seu resolvedor direto do Lambda configurando `maxBatchSize` no seu resolvedor. Quando `maxBatchSize` é definido com um valor maior do que `0` para um resolvedor do Direct Lambda, AWS AppSync envia solicitações em lotes para sua função Lambda em tamanhos de até. `maxBatchSize` 

Definir `maxBatchSize` como `0` em um resolvedor direto do Lambda desativa o agrupamento em lotes.

Para obter mais informações sobre como funciona o agrupamento em lotes com os resolvedores do Lambda, consulte [Caso de uso avançado: agrupamento em lotes](tutorial-lambda-resolvers.md#advanced-use-case-batching).

#### Modelo de mapeamento de solicitações
<a name="lambda-resolvers-batching-request-template"></a>

Quando o agrupamento em lotes está ativado e o modelo de mapeamento da solicitação não é fornecido, AWS AppSync envia uma lista de `Context` objetos como uma `BatchInvoke` operação diretamente para sua função Lambda.

#### Modelo de mapeamento de respostas
<a name="lambda-resolvers-batching-response-template"></a>

Quando o agrupamento em lote está ativado e o modelo de mapeamento de resposta não é fornecido, a lógica de resposta é equivalente ao seguinte modelo de mapeamento de resposta:

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

A função do Lambda deve retornar uma lista de resultados na mesma ordem da lista de objetos `Context` que foram enviados. É possível retornar erros individuais fornecendo `errorMessage` e `errorType` para um resultado específico. Cada resultado na lista deve estar no seguinte formato:

```
{
   "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**  
Outros campos no objeto de resultado são ignorados.

#### Manuseio de erros do Lambda
<a name="lambda-resolvers-batching-error-handling"></a>

Você pode retornar um erro para todos os resultados lançando uma exceção ou um erro na sua função do Lambda. Se a solicitação de payload ou o tamanho da resposta para sua solicitação em lote for muito grande, o Lambda retornará um erro. Nesse caso, você deve considerar reduzir `maxBatchSize` ou o tamanho do payload da resposta.

Para obter informações sobre como lidar com erros individuais, consulte [Retornar erros individuais](tutorial-lambda-resolvers.md#returning-individual-errors).

#### Amostra de função do Lambda
<a name="sample-lambda-function"></a>

Usando o esquema abaixo, você pode criar um resolvedor direto do Lambda para o resolvedor de campo `Post.relatedPosts` e habilitar o agrupamento em lote definindo `maxBatchSize` acima de `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]
}
```

Na consulta a seguir, a função do Lambda será chamada com lotes de solicitações para resolver `relatedPosts`:

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

Confira abaixo uma implementação simples de uma função do 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' }
    }
  })
}
```