

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á.

# Usando AWS Lambda resolvedores em AWS AppSync
<a name="tutorial-lambda-resolvers"></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/tutorials-js.html).

Você pode usar AWS Lambda with AWS AppSync para resolver qualquer campo do GraphQL. Por exemplo, uma consulta do GraphQL pode enviar uma chamada para uma instância do Amazon Relational Database Service (Amazon RDS), e uma mutação do GraphQL pode ser gravada em um stream do Amazon Kinesis. Nesta seção, mostraremos como escrever uma função do Lambda que executa lógica de negócios com base na invocação de uma operação de campo do GraphQL.

## Criar uma função do Lambda
<a name="create-a-lam-function"></a>

O exemplo a seguir mostra uma função do Lambda escrita em `Node.js` que realiza operações diferentes em publicações de blog como parte de um aplicativo de publicação de blog.

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var 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"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got an Invoke Request.");
    switch(event.field) {
        case "getPost":
            var id = event.arguments.id;
            callback(null, posts[id]);
            break;
        case "allPosts":
            var values = [];
            for(var d in posts){
                values.push(posts[d]);
            }
            callback(null, values);
            break;
        case "addPost":
            // return the arguments back
            callback(null, event.arguments);
            break;
        case "addPostErrorWithData":
            var id = event.arguments.id;
            var result = posts[id];
            // attached additional error information to the post
            result.errorMessage = 'Error with the mutation, data has changed';
            result.errorType = 'MUTATION_ERROR';
            callback(null, result);
            break;
        case "relatedPosts":
            var id = event.source.id;
            callback(null, relatedPosts[id]);
            break;
        default:
            callback("Unknown field, unable to resolve" + event.field, null);
            break;
    }
};
```

Essa função do Lambda recupera uma publicação por ID, adiciona uma publicação, recupera uma lista de publicações e busca publicações relacionadas para determinada publicação.

 **Observação:** a função do Lambda usa a instrução `switch` em `event.field` para determinar qual campo está sendo resolvido no momento.

Crie essa função Lambda usando o console AWS de gerenciamento ou uma AWS CloudFormation pilha. Para criar a função a partir de uma CloudFormation pilha, você pode usar o seguinte comando AWS Command Line Interface (AWS CLI):

```
aws cloudformation create-stack --stack-name AppSyncLambdaExample \
--template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/lambda/LambdaCFTemplate.yaml \
--capabilities CAPABILITY_NAMED_IAM
```

Você também pode lançar a CloudFormation pilha na AWS região Oeste dos EUA (Oregon) em sua AWS conta aqui:

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

## Configurar a fonte de dados para o Lambda
<a name="configure-data-source-for-lamlong"></a>

Depois de criar a função do Lambda, navegue até a API GraphQL no console AWS AppSync e escolha a guia **Fontes de dados**.

Escolha **Criar fonte de dados**, insira um **Nome de fonte de dados** fácil de usar (por exemplo, **Lambda**) e, em seguida, para **Tipo de fonte de dados**, escolha **Função AWS Lambda **. Em **Região**, escolha a mesma região que a de sua função. (Se você criou a função a partir da CloudFormation pilha fornecida, a função provavelmente está em **US-WEST-2**.) Para **ARN da função do Lambda**, escolha o nome do recurso da Amazon (ARN) da sua função do Lambda.

Depois de escolher sua função Lambda, você pode criar uma nova função AWS Identity and Access Management (IAM) (para a qual AWS AppSync atribui as permissões apropriadas) ou escolher uma função existente que tenha a seguinte política embutida:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:us-east-1:111122223333:function:LAMBDA_FUNCTION"
        }
    ]
}
```

------

Você também deve configurar uma relação de confiança com AWS AppSync a função do IAM da seguinte forma:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

## Criar um esquema do GraphQL
<a name="creating-a-graphql-schema"></a>

Agora que a fonte de dados está conectada à função do Lambda, crie um esquema do GraphQL.

No editor de esquemas no AWS AppSync console, certifique-se de que seu esquema corresponda ao seguinte esquema:

```
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]
}
```

## Configurar resolvedores
<a name="configuring-resolvers"></a>

Agora que você registrou uma fonte de dados do Lambda e um esquema do GraphQL válido, pode conectar seus campos do GraphQL à sua fonte de dados do Lambda usando resolvedores.

Para criar um resolvedor, você precisará de modelos de mapeamento. Para saber mais sobre modelos de mapeamento, consulte [Resolver Mapping Template Overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

Para obter mais informações sobre modelos de mapeamento do Lambda, consulte [Resolver mapping template reference for Lambda](resolver-mapping-template-reference-lambda.md#aws-appsync-resolver-mapping-template-reference-lambda).

Nesta etapa, você anexa um resolvedor à função do Lambda para os seguintes campos: `getPost(id:ID!): Post`, `allPosts: [Post]`, `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!` e `Post.relatedPosts: [Post]`.

No editor de esquemas no AWS AppSync console, no lado direito, escolha **Anexar resolvedor** para`getPost(id:ID!): Post`.

Depois, no **menu Ação**, escolha **Atualizar runtime** e selecione **Resolvedor de unidade (somente VTL)**.

Depois, escolha sua fonte de dados do Lambda. Na seção **modelo de mapeamento da solicitação**, escolha **Invocar e encaminhar argumentos**.

Modifique o objeto `payload` para adicionar o nome do campo. O modelo deve ser semelhante ao seguinte:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "arguments":  $utils.toJson($context.arguments)
    }
}
```

Na seção **modelo de mapeamento da resposta**, escolha **Retornar o resultado Lambda**.

Nesse caso, use o modelo base como está. Ele deve ter a seguinte aparência:

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

Escolha **Salvar**. Você anexou seu primeiro resolvedor com sucesso. Repita essa operação para os campos restantes da seguinte forma:

Para o modelo de mapeamento da solicitação `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "addPost",
        "arguments":  $utils.toJson($context.arguments)
    }
}
```

Para o modelo de mapeamento da resposta `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!`:

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

Para o modelo de mapeamento da solicitação `allPosts: [Post]`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "allPosts"
    }
}
```

Para o modelo de mapeamento da resposta `allPosts: [Post]`:

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

Para o modelo de mapeamento da solicitação `Post.relatedPosts: [Post]`:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "relatedPosts",
        "source":  $utils.toJson($context.source)
    }
}
```

Para o modelo de mapeamento da resposta `Post.relatedPosts: [Post]`:

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

## Teste da sua API GraphQL
<a name="testing-your-graphql-api"></a>

Agora que a função do Lambda está conectada aos resolvedores do GraphQL, você pode executar algumas mutações e consultas usando o console ou um aplicativo cliente.

No lado esquerdo do AWS AppSync console, escolha **Consultas** e cole o código a seguir:

### Mutação addPost
<a name="addpost-mutation"></a>

```
mutation addPost {
    addPost(
        id: 6
        author: "Author6"
        title: "Sixth book"
        url: "https://www.amazon.com/"
        content: "This is the book is a tutorial for using GraphQL with AWS AppSync."
    ) {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### Consulta getPost
<a name="getpost-query"></a>

```
query getPost {
    getPost(id: "2") {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### Consulta allPosts
<a name="allposts-query"></a>

```
query allPosts {
    allPosts {
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {
            id
            title
        }
    }
}
```

## Retornar erros
<a name="returning-errors"></a>

Qualquer resolução de campo determinada pode resultar em um erro. Com AWS AppSync, você pode gerar erros das seguintes fontes:
+ Modelo de mapeamento da solicitação ou resposta
+ Função do Lambda

### A partir do modelo de mapeamento
<a name="from-the-mapping-template"></a>

Para gerar erros intencionais, você pode usar o método auxiliar `$utils.error` do modelo VTL (Velocity Template Language). Ele utiliza como argumento uma `errorMessage`, um `errorType` e um valor `data` opcional. O `data` é útil para retornar dados adicionais de volta ao cliente quando ocorre um erro. O objeto `data` é adicionado ao `errors` na resposta final do GraphQL.

O exemplo a seguir mostra como usá-lo no modelo de mapeamento da resposta `Post.relatedPosts: [Post]`:

```
$utils.error("Failed to fetch relatedPosts", "LambdaFailure", $context.result)
```

Isso produz uma resposta do GraphQL semelhante à seguinte:

```
{
    "data": {
        "allPosts": [
            {
                "id": "2",
                "title": "Second book",
                "relatedPosts": null
            },
            ...
        ]
    },
    "errors": [
        {
            "path": [
                "allPosts",
                0,
                "relatedPosts"
            ],
            "errorType": "LambdaFailure",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ],
            "message": "Failed to fetch relatedPosts",
            "data": [
                {
                  "id": "2",
                  "title": "Second book"
                },
                {
                  "id": "1",
                  "title": "First book"
                }
            ]
        }
    ]
}
```

Em que `allPosts[0].relatedPosts` é *nulo*, pois o erro e o `errorMessage`, o `errorType` e o `data` estão presentes no objeto `data.errors[0]`.

### A partir da função do Lambda
<a name="from-the-lam-function"></a>

AWS AppSync também compreende os erros que a função Lambda gera. O modelo de programação do Lambda permite gerar erros *processados*. Se a função Lambda gerar um erro, AWS AppSync não conseguirá resolver o campo atual. Somente a mensagem de erro retornada a partir do Lambda é definida na resposta. No momento, não é possível enviar quaisquer dados adicionais de volta para o cliente ao gerar um erro a partir da função do Lambda.

 **Observação**: se sua função Lambda gerar um erro *não tratado*, AWS AppSync use a mensagem de erro que o Lambda definiu.

A seguinte função do Lambda gera um erro:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    callback("I fail. Always.");
};
```

Isso retorna uma resposta do GraphQL semelhante à seguinte:

```
{
    "data": {
        "allPosts": [
            {
                "id": "2",
                "title": "Second book",
                "relatedPosts": null
            },
            ...
        ]
    },
    "errors": [
        {
            "path": [
                "allPosts",
                0,
                "relatedPosts"
            ],
            "errorType": "Lambda:Handled",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ],
            "message": "I fail. Always."
        }
    ]
}
```

## Caso de uso avançado: agrupamento em lotes
<a name="advanced-use-case-batching"></a>

Neste exemplo, a função do Lambda tem um campo `relatedPosts` que retorna uma lista de publicações relacionadas para uma publicação. Nas consultas de exemplo, a invocação do campo `allPosts` a partir da função do Lambda retorna cinco publicações. Como também especificamos que queremos resolver `relatedPosts` para cada publicação retornada, a operação do campo `relatedPosts` será invocada cinco vezes.

```
query allPosts {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yields 5 posts
            id
            title
        }
    }
}
```

Embora isso possa não parecer substancial neste exemplo específico, essa busca excessiva combinada pode prejudicar rapidamente o aplicativo.

Se você buscasse `relatedPosts` novamente nas `Posts` relacionadas retornadas na mesma consulta, o número de invocações aumentaria drasticamente.

```
query allPosts {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yield 5 posts = 5 x 5 Posts
            id
            title
            relatedPosts {  // 5 x 5 Lambda invocations - each yield 5 posts = 25 x 5 Posts
                id
                title
                author
            }
        }
    }
}
```

Nessa consulta relativamente simples, AWS AppSync invocaria a função Lambda 1 \$1 5 \$1 25 = 31 vezes.

Esse é um desafio bastante comum e normalmente é chamado de problema N\$11 (nesse caso, N = 5) e pode incorrer em maior latência e mais custo para o aplicativo.

Uma forma de resolver esse problema é agrupar solicitações do resolvedor de campo semelhantes em lotes. Nesse exemplo, em vez da função do Lambda resolver uma lista de publicações relacionadas para uma única publicação, ela resolveria uma lista de publicações relacionadas para um determinado lote de publicações.

Para demonstrar isso, vamos alternar o resolvedor `Post.relatedPosts: [Post]` para um resolvedor habilitado para lotes.

No lado direito do AWS AppSync console, escolha o `Post.relatedPosts: [Post]` resolvedor existente. Altere o modelo de mapeamento da solicitação para o seguinte:

```
{
    "version": "2017-02-28",
    "operation": "BatchInvoke",
    "payload": {
        "field": "relatedPosts",
        "source":  $utils.toJson($context.source)
    }
}
```

Somente o campo `operation` foi alterado de `Invoke` para `BatchInvoke`. O campo de carga útil agora se torna uma matriz do que é especificado no modelo. Neste exemplo, a função do Lambda recebe o seguinte como entrada:

```
[
    {
        "field": "relatedPosts",
        "source": {
            "id": 1
        }
    },
    {
        "field": "relatedPosts",
        "source": {
            "id": 2
        }
    },
    ...
]
```

Quando `BatchInvoke` for especificado no modelo de mapeamento da solicitação, a função do Lambda recebe uma lista de solicitações e retorna uma lista de resultados.

Especificamente, a lista de resultados deve corresponder ao tamanho e à ordem das entradas da carga útil da solicitação para que AWS AppSync possa corresponder aos resultados adequadamente.

Neste exemplo de processamento em lotes, a função do Lambda retorna um lote de resultados da seguinte forma:

```
[
    [{"id":"2","title":"Second book"}, {"id":"3","title":"Third book"}],   // relatedPosts for id=1
    [{"id":"3","title":"Third book"}]                                                             // relatedPosts for id=2
]
```

A seguinte função do Lambda em Node.js demonstra essa funcionalidade de agrupamento em lotes para o campo `Post.relatedPosts` da seguinte forma:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var 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"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got a BatchInvoke Request. The payload has %d items to resolve.", event.length);
    // event is now an array
    var field = event[0].field;
    switch(field) {
        case "relatedPosts":
            var results = [];
            // the response MUST contain the same number
            // of entries as the payload array
            for (var i=0; i< event.length; i++) {
                console.log("post {}", JSON.stringify(event[i].source));
                results.push(relatedPosts[event[i].source.id]);
            }
            console.log("results {}", JSON.stringify(results));
            callback(null, results);
            break;
        default:
            callback("Unknown field, unable to resolve" + field, null);
            break;
    }
};
```

### Retornar erros individuais
<a name="returning-individual-errors"></a>

Os exemplos anteriores mostram que é possível retornar um único erro a partir da função do Lambda ou gerar um erro a partir dos modelos de mapeamento. Para invocações em lote, gerar um erro a partir da função do Lambda sinaliza um lote inteiro como falho. Isso pode ser aceitável em cenários específicos onde ocorreu um erro irrecuperável, como uma conexão com falha a um armazenamento de dados. No entanto, nos casos em que alguns itens no lote são bem-sucedidos e outros falham, é possível retornar ambos os erros e os dados válidos. Como AWS AppSync exige a resposta em lote para listar elementos que correspondam ao tamanho original do lote, você deve definir uma estrutura de dados que possa diferenciar dados válidos de um erro.

Por exemplo, se houver expectativa da função do Lambda retornar um lote de publicações relacionadas, você poderá optar por retornar uma lista de objetos `Response` em que cada objeto tem campos *data*, *errorMessage* e *errorType* opcionais. Se o campo *errorMessage* estiver presente, isso significa que ocorreu um erro.

O código a seguir mostra como você pode atualizar a função do Lambda:

```
exports.handler = (event, context, callback) => {
    console.log("Received event {}", JSON.stringify(event, 3));
    var 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"} };

    var relatedPosts = {
        "1": [posts['4']],
        "2": [posts['3'], posts['5']],
        "3": [posts['2'], posts['1']],
        "4": [posts['2'], posts['1']],
        "5": []
    };

    console.log("Got a BatchInvoke Request. The payload has %d items to resolve.", event.length);
    // event is now an array
    var field = event[0].field;
    switch(field) {
        case "relatedPosts":
            var results = [];
            results.push({ 'data': relatedPosts['1'] });
            results.push({ 'data': relatedPosts['2'] });
            results.push({ 'data': null, 'errorMessage': 'Error Happened', 'errorType': 'ERROR' });
            results.push(null);
            results.push({ 'data': relatedPosts['3'], 'errorMessage': 'Error Happened with last result', 'errorType': 'ERROR' });
            callback(null, results);
            break;
        default:
            callback("Unknown field, unable to resolve" + field, null);
            break;
    }
};
```

Para este exemplo, o modelo de mapeamento da resposta a seguir analisa cada item da função do Lambda e sinaliza os erros que ocorrerem:

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

Esse exemplo retorna uma resposta do GraphQL semelhante à seguinte:

```
{
  "data": {
    "allPosts": [
      {
        "id": "1",
        "relatedPostsPartialErrors": [
          {
            "id": "4",
            "title": "Fourth book"
          }
        ]
      },
      {
        "id": "2",
        "relatedPostsPartialErrors": [
          {
            "id": "3",
            "title": "Third book"
          },
          {
            "id": "5",
            "title": "Fifth book"
          }
        ]
      },
      {
        "id": "3",
        "relatedPostsPartialErrors": null
      },
      {
        "id": "4",
        "relatedPostsPartialErrors": null
      },
      {
        "id": "5",
        "relatedPostsPartialErrors": null
      }
    ]
  },
  "errors": [
    {
      "path": [
        "allPosts",
        2,
        "relatedPostsPartialErrors"
      ],
      "errorType": "ERROR",
      "locations": [
        {
          "line": 4,
          "column": 9
        }
      ],
      "message": "Error Happened"
    },
    {
      "path": [
        "allPosts",
        4,
        "relatedPostsPartialErrors"
      ],
      "data": [
        {
          "id": "2",
          "title": "Second book"
        },
        {
          "id": "1",
          "title": "First book"
        }
      ],
      "errorType": "ERROR",
      "locations": [
        {
          "line": 4,
          "column": 9
        }
      ],
      "message": "Error Happened with last result"
    }
  ]
}
```

### Configuração do tamanho máximo do lote
<a name="configure-max-batch-size"></a>

Por padrão, ao usar`BatchInvoke`, AWS AppSync envia solicitações para sua função Lambda em lotes de até cinco itens. Você pode configurar o tamanho máximo do lote dos seus resolvedores do Lambda.

Para configurar o tamanho máximo de lotes em um resolvedor, use o seguinte comando no AWS Command Line Interface (AWS CLI):

```
$ aws appsync create-resolver --api-id <api-id> --type-name Query --field-name relatedPosts \
 --request-mapping-template "<template>" --response-mapping-template "<template>" --data-source-name "<lambda-datasource>" \ 
 --max-batch-size X
```

**nota**  
Ao fornecer um modelo de mapeamento de solicitação, você deve usar a operação `BatchInvoke` para usar lotes.

Você também pode usar o seguinte comando para ativar e configurar o lote em resolvedores diretos do Lambda:

```
$ aws appsync create-resolver --api-id <api-id> --type-name Query --field-name relatedPosts \
 --data-source-name "<lambda-datasource>" \ 
 --max-batch-size X
```

### Configuração de tamanho máximo de lote com modelos VTL
<a name="configure-max-batch-size-vtl"></a>

Para resolvedores do Lambda que possuem modelos de solicitação de VTL, o tamanho máximo do lote não terá efeito, a menos que o tenham especificado diretamente como uma operação `BatchInvoke` em VTL. Da mesma forma, se você estiver executando uma mutação de nível superior, o processamento em lote não será conduzido para mutações porque a especificação do GraphQL exige que mutações paralelas sejam executadas sequencialmente.

Por exemplo, considere as seguintes mutações:

```
type Mutation {
    putItem(input: Item): Item
    putItems(inputs: [Item]): [Item]
}
```

Usando a primeira mutação, podemos criar 10 `Items` conforme mostrado no trecho abaixo:

```
mutation MyMutation {
    v1: putItem($someItem1) {
        id,
        name
    }
    v2: putItem($someItem2) {
        id,
        name
    }
    v3: putItem($someItem3) {
        id,
        name
    } 
    v4: putItem($someItem4) {
        id,
        name
    }
    v5: putItem($someItem5) {
        id,
        name
    }
    v6: putItem($someItem6) {
        id,
        name
    } 
    v7: putItem($someItem7) {
        id,
        name
    }
    v8: putItem($someItem8) {
        id,
        name
    }
    v9: putItem($someItem9) {
        id,
        name
    }
    v10: putItem($someItem10) {
        id,
        name
    }
}
```

Neste exemplo, os `Items` não serão agrupados em um grupo de 10, mesmo que o tamanho máximo do lote seja definido como 10 no resolvedor do Lambda. Em vez disso, eles serão executados sequencialmente de acordo com a especificação do GraphQL.

Para realizar uma mutação em lote real, você pode seguir o exemplo abaixo usando a segunda mutação:

```
mutation MyMutation {
    putItems([$someItem1, $someItem2, $someItem3,$someItem4, $someItem5, $someItem6, 
    $someItem7, $someItem8, $someItem9, $someItem10]) {
    id,
    name
    }
}
```

Para obter mais informações sobre como usar lotes com resolvedores diretos do Lambda, consulte [Resolvedores diretos do Lambda](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers).