

# Invocar função do AWS Lambda
<a name="batch-ops-invoke-lambda"></a>

Você pode usar o Operações em Lote do Amazon S3 para executar operações em lote de grande escala em objetos do Amazon S3. A operação do Operações em Lote da **função Invocar do AWS Lambda** inicia as funções do AWS Lambda para executar ações personalizadas em objetos que estão listados em um manifesto. Esta seção descreve como criar uma função do Lambda para uso com as operações em lote do S3 e como criar um trabalho para chamar a função. O trabalho de Operações em lote do S3 usa a operação `LambdaInvoke` para executar uma função do Lambda em cada objeto listado em um manifesto.

Você pode trabalhar com o Operações em Lote do S3 usando o console do Amazon S3, a AWS Command Line Interface (AWS CLI), SDKs da AWS ou a API REST do Amazon S3. Para obter mais informações sobre como usar o Lambda, consulte [Conceitos básicos do AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html) no *Guia do desenvolvedor do AWS Lambda*. 

As seções a seguir explicam como começar a usar as operações em lote do S3 com o Lambda.

**Topics**
+ [

## Usar o Lambda com o Operações em Lote
](#batch-ops-invoke-lambda-using)
+ [

## Criar uma função do Lambda para uso com operações em lote do S3
](#batch-ops-invoke-lambda-custom-functions)
+ [

## Criar um trabalho de operações em lote do S3 que chama uma função do Lambda
](#batch-ops-invoke-lambda-create-job)
+ [

## Fornecer informações em nível de tarefa em manifestos do Lambda
](#storing-task-level-information-in-lambda)
+ [

## Tutorial Operações em lote do S3
](#batch-ops-tutorials-lambda)

## Usar o Lambda com o Operações em Lote
<a name="batch-ops-invoke-lambda-using"></a>

Ao usar o S3 Batch Operations com o AWS Lambda, crie novas funções do Lambda especificamente para uso com o S3 Batch Operations. Não é possível reutilizar funções baseadas em eventos do Amazon S3 existentes com operações em lote do S3. As funções de eventos só podem receber mensagens; elas não retornam mensagens. As funções do Lambda usadas com operações em lote do S3 devem aceitar e retornar mensagens. Para obter mais informações sobre como usar o Lambda com eventos do Amazon S3, consulte [Uso do AWS Lambda com o Amazon S3](https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html) no *Guia do desenvolvedor do AWS Lambda*.

Crie um trabalho de operações em lote do S3 que chame a função do Lambda. O trabalho executa a mesma função do Lambda em todos os objetos listados no manifesto. É possível controlar quais versões da função do Lambda usar durante o processamento dos objetos no manifesto. As operações em lote do S3 são compatíveis com nomes de recursos da Amazon (ARNs) não qualificados, aliases e versões específicas. Para obter mais informações, consulte [Introdução ao versionamento do AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/versioning-intro.html) no *Guia do desenvolvedor do AWS Lambda*.

Se você fornecer ao trabalho de operações em lote do S3 um ARN de função que usa um alias ou o qualificador `$LATEST`, e atualizar a versão indicada por um deles, as operações em lote do S3 começarão a chamar a nova versão dessa função do Lambda. Isso pode ser útil quando você quer atualizar a funcionalidade durante um trabalho grande. Se você não quer que o Operações em Lote do S3 altere a versão usada, forneça a versão específica no parâmetro `FunctionARN` ao criar o trabalho.

Um único trabalho do AWS Lambda com o recurso Operações em Lote do S3 pode comportar um manifesto com até 20 bilhões de objetos.

### Usar o Lambda e o Operações em Lote com buckets de diretório
<a name="batch-ops-invoke-lambda-directory-buckets"></a>

Os buckets de diretório são um tipo de bucket do Amazon S3 projetado para workloads ou aplicações essenciais à performance que requerem latência consistente inferior a dez milissegundos. Para obter mais informações, consulte [Directory buckets](https://docs.aws.amazon.com//AmazonS3/latest/userguide/directory-buckets-overview.html).

Há requisitos especiais para usar a funcionalidade Operações em Lote para invocar funções do Lambda que atuam em buckets de diretório. Por exemplo, você deve estruturar a solicitação do Lambda usando um esquema JSON atualizado e especificar [https://docs.aws.amazon.com//AmazonS3/latest/API/API_control_LambdaInvokeOperation.html#AmazonS3-Type-control_LambdaInvokeOperation-InvocationSchemaVersion](https://docs.aws.amazon.com//AmazonS3/latest/API/API_control_LambdaInvokeOperation.html#AmazonS3-Type-control_LambdaInvokeOperation-InvocationSchemaVersion) 2.0 (não 1.0) ao criar o trabalho. Esse esquema atualizado permite que você especifique pares opcionais de chave e valor para [https://docs.aws.amazon.com//AmazonS3/latest/API/API_control_LambdaInvokeOperation.html#AmazonS3-Type-control_LambdaInvokeOperation-UserArguments](https://docs.aws.amazon.com//AmazonS3/latest/API/API_control_LambdaInvokeOperation.html#AmazonS3-Type-control_LambdaInvokeOperation-UserArguments), que você pode usar para modificar determinados parâmetros de funções do Lambda existentes. Consulte mais informações em [Automate object processing in Amazon S3 directory buckets with S3 Batch Operations and AWS Lambda](https://aws.amazon.com/blogs/storage/automate-object-processing-in-amazon-s3-directory-buckets-with-s3-batch-operations-and-aws-lambda/) no Blog de armazenamento da AWS.

### Códigos de resultado e resposta
<a name="batch-ops-invoke-lambda-response-codes"></a>

A funcionalidade Operações em Lote do S3 invoca a função do Lambda com uma ou mais chaves, cada uma com um `TaskID` associado. A funcionalidade Operações em Lote do S3 espera um código de resultado por chave das funções do Lambda. Todos os IDs de tarefas enviados na solicitação que não forem retornados com um código de resultado por chave receberão o código de resultado do campo `treatMissingKeysAs`. `treatMissingKeysAs` é um campo de solicitação opcional e o padrão é `TemporaryFailure`. A tabela a seguir contém os outros códigos de resultado e valores possíveis para o campo `treatMissingKeysAs`. 


| Código de resposta | Descrição | 
| --- | --- | 
| Succeeded | A tarefa foi concluída normalmente. Se você solicitou um relatório de conclusão do trabalho, a string do resultado da tarefa será incluída no relatório. | 
| TemporaryFailure | A tarefa sofreu uma falha temporária e será redirecionada antes da conclusão do trabalho. A string de resultado é ignorada. Se esse for o redirecionamento final, a mensagem de erro será incluída no relatório final. | 
| PermanentFailure | A tarefa sofreu uma falha permanente. Se você solicitou um relatório de conclusão do trabalho, a tarefa será marcada como Failed e incluirá a string da mensagem de erro. As strings de resultado de tarefas com falha são ignoradas. | 

## Criar uma função do Lambda para uso com operações em lote do S3
<a name="batch-ops-invoke-lambda-custom-functions"></a>

Essa seção fornece um exemplo de permissões do AWS Identity and Access Management (IAM) que devem ser usadas com a função do Lambda. Ela também contém um exemplo de função do Lambda para uso com operações em lote do S3. Se você nunca criou uma função do Lambda antes, consulte [Tutorial: Como usar um trigger do Amazon S3 para invocar uma função do AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html) no *Guia do desenvolvedor do AWS Lambda*.

Crie funções do Lambda especificamente para uso com as operações em lote do S3. Não é possível reutilizar funções do Lambda baseadas em eventos do Amazon S3, pois as funções do Lambda que são usadas para o Operações em Lote do S3 devem aceitar e mostrar campos de dados especiais. 

**Importante**  
Funções do AWS Lambda escritas em Java aceitam interfaces de manipulador [https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java) ou [https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java). No entanto, para oferecer suporte ao formato de solicitação e resposta do S3 Batch Operations, o AWS Lambda requer a interface `RequestStreamHandler` para serialização e desserialização personalizadas de uma solicitação e resposta. Essa interface permite que o Lambda passe um InputStream e um OutputStream para o método Java `handleRequest`.   
Use a interface `RequestStreamHandler` ao usar funções do Lambda com operações em lote do S3. Se você usar uma interface `RequestHandler`, o trabalho em lote falhará com “Invalid JSON returned in Lambda payload (JSON inválido retornado no payload do Lambda)” no relatório de conclusão.   
Para obter mais informações, consulte [Interfaces do manipulador](https://docs.aws.amazon.com//lambda/latest/dg/java-handler.html#java-handler-interfaces) no *Guia do usuário do AWS Lambda*.

### Exemplo de permissões do IAM
<a name="batch-ops-invoke-lambda-custom-functions-iam"></a>

Veja a seguir exemplos das permissões do IAM necessárias para usar uma função do Lambda com operações em lote do S3. 

**Example Política de confiança de operações em lote do S3**  
Veja a seguir um exemplo da política de confiança que pode ser usada para a função do IAM de operações em lote. Essa função do IAM é especificada quando você cria o trabalho e concede às operações em lote permissão para assumir a função do IAM.    
****  

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

**Example Política do IAM do Lambda**  
Veja a seguir um exemplo de uma política do IAM que concede permissão às operações em lote do S3 para chamar a função do Lambda e ler o manifesto de entrada.    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "BatchOperationsLambdaPolicy",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:PutObject",
                "lambda:InvokeFunction"
            ],
            "Resource": "*"
        }
    ]
}
```

### Exemplo de solicitação e resposta
<a name="batch-ops-invoke-lambda-custom-functions-request"></a>

Esta seção fornece exemplos de solicitação e resposta para a função do Lambda.

**Example Solicitação**  
Veja a seguir um exemplo do JSON de uma solicitação para a função do Lambda.  

```
{
    "invocationSchemaVersion": "1.0",
    "invocationId": "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo",
    "job": {
        "id": "f3cc4f60-61f6-4a2b-8a21-d07600c373ce"
    },
    "tasks": [
        {
            "taskId": "dGFza2lkZ29lc2hlcmUK",
            "s3Key": "customerImage1.jpg",
            "s3VersionId": "1",
            "s3BucketArn": "arn:aws:s3:us-east-1:0123456788:amzn-s3-demo-bucket1"
        }
    ]
}
```

**Example Resposta**  
Veja a seguir um exemplo do JSON de uma resposta para a função do Lambda.  

```
{
  "invocationSchemaVersion": "1.0",
  "treatMissingKeysAs" : "PermanentFailure",
  "invocationId" : "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo",
  "results": [
    {
      "taskId": "dGFza2lkZ29lc2hlcmUK",
      "resultCode": "Succeeded",
      "resultString": "[\"Mary Major", \"John Stiles\"]"
    }
  ]
}
```

### Exemplo de função do Lambda para operações em lote do S3
<a name="batch-ops-invoke-lambda-custom-functions-example"></a>

O exemplo Lambda em Python a seguir remove um marcador de exclusão de um objeto versionado.

Como mostra o exemplo, as chaves das operações em lote do S3 são codificadas por URL. Para usar o Amazon S3 com outros produtos da AWS, é importante que seu URL decodifique a chave passada pelo S3 Batch Operations.

```
import logging
from urllib import parse
import boto3
from botocore.exceptions import ClientError

logger = logging.getLogger(__name__)
logger.setLevel("INFO")

s3 = boto3.client("s3")


def lambda_handler(event, context):
    """
    Removes a delete marker from the specified versioned object.

    :param event: The S3 batch event that contains the ID of the delete marker
                  to remove.
    :param context: Context about the event.
    :return: A result structure that Amazon S3 uses to interpret the result of the
             operation. When the result code is TemporaryFailure, S3 retries the
             operation.
    """
    # Parse job parameters from Amazon S3 batch operations
    invocation_id = event["invocationId"]
    invocation_schema_version = event["invocationSchemaVersion"]

    results = []
    result_code = None
    result_string = None

    task = event["tasks"][0]
    task_id = task["taskId"]

    try:
        obj_key = parse.unquote_plus(task["s3Key"], encoding="utf-8")
        obj_version_id = task["s3VersionId"]
        bucket_name = task["s3BucketArn"].split(":")[-1]

        logger.info(
            "Got task: remove delete marker %s from object %s.", obj_version_id, obj_key
        )

        try:
            # If this call does not raise an error, the object version is not a delete
            # marker and should not be deleted.
            response = s3.head_object(
                Bucket=bucket_name, Key=obj_key, VersionId=obj_version_id
            )
            result_code = "PermanentFailure"
            result_string = (
                f"Object {obj_key}, ID {obj_version_id} is not " f"a delete marker."
            )

            logger.debug(response)
            logger.warning(result_string)
        except ClientError as error:
            delete_marker = error.response["ResponseMetadata"]["HTTPHeaders"].get(
                "x-amz-delete-marker", "false"
            )
            if delete_marker == "true":
                logger.info(
                    "Object %s, version %s is a delete marker.", obj_key, obj_version_id
                )
                try:
                    s3.delete_object(
                        Bucket=bucket_name, Key=obj_key, VersionId=obj_version_id
                    )
                    result_code = "Succeeded"
                    result_string = (
                        f"Successfully removed delete marker "
                        f"{obj_version_id} from object {obj_key}."
                    )
                    logger.info(result_string)
                except ClientError as error:
                    # Mark request timeout as a temporary failure so it will be retried.
                    if error.response["Error"]["Code"] == "RequestTimeout":
                        result_code = "TemporaryFailure"
                        result_string = (
                            f"Attempt to remove delete marker from  "
                            f"object {obj_key} timed out."
                        )
                        logger.info(result_string)
                    else:
                        raise
            else:
                raise ValueError(
                    f"The x-amz-delete-marker header is either not "
                    f"present or is not 'true'."
                )
    except Exception as error:
        # Mark all other exceptions as permanent failures.
        result_code = "PermanentFailure"
        result_string = str(error)
        logger.exception(error)
    finally:
        results.append(
            {
                "taskId": task_id,
                "resultCode": result_code,
                "resultString": result_string,
            }
        )
    return {
        "invocationSchemaVersion": invocation_schema_version,
        "treatMissingKeysAs": "PermanentFailure",
        "invocationId": invocation_id,
        "results": results,
    }
```

## Criar um trabalho de operações em lote do S3 que chama uma função do Lambda
<a name="batch-ops-invoke-lambda-create-job"></a>

Ao criar um trabalho de operações em lote do S3 para chamar uma função do Lambda, forneça o seguinte:
+ O ARN da função do Lambda (que pode incluir o alias da função ou o número de uma versão específica)
+ Uma função do IAM com permissão para invocar a função
+ O parâmetro de ação `LambdaInvokeFunction`

Para obter mais informações sobre como criar um trabalho de operações em lote do S3, consulte [Criar um trabalho de operações em lote do S3](batch-ops-create-job.md) e [Operações suportadas pelo S3 Batch Operations](batch-ops-operations.md).

O exemplo a seguir cria um trabalho do Operações em Lote do S3 que invoca uma função do Lambda usando a AWS CLI. Para usar esse exemplo, substitua os *`user input placeholders`* por suas próprias informações.

```
aws s3control create-job
    --account-id account-id
    --operation  '{"LambdaInvoke": { "FunctionArn": "arn:aws:lambda:region:account-id:function:LambdaFunctionName" } }'
    --manifest '{"Spec":{"Format":"S3BatchOperations_CSV_20180820","Fields":["Bucket","Key"]},"Location":{"ObjectArn":"arn:aws:s3:::amzn-s3-demo-manifest-bucket","ETag":"ManifestETag"}}'
    --report '{"Bucket":"arn:aws:s3:::amzn-s3-demo-bucket","Format":"Report_CSV_20180820","Enabled":true,"Prefix":"ReportPrefix","ReportScope":"AllTasks"}'
    --priority 2
    --role-arn arn:aws:iam::account-id:role/BatchOperationsRole
    --region region
    --description "Lambda Function"
```

## Fornecer informações em nível de tarefa em manifestos do Lambda
<a name="storing-task-level-information-in-lambda"></a>

Ao usar funções do AWS Lambda com o Operações em Lote do S3, talvez você queira que dados adicionais acompanhem cada tarefa em que são operados. Por exemplo, você pode querer fornecer uma chave de objeto de origem e uma nova chave de objeto. A função do Lambda pode copiar a chave de origem em um novo bucket do S3 com um novo nome. Por padrão, o Operações em Lote permite especificar apenas o bucket de destino e uma lista de chaves de origem no manifesto de entrada do trabalho. Os exemplos a seguir descrevem como você pode incluir dados adicionais no manifesto para poder executar funções do Lambda mais complexas.

Para especificar parâmetros por chave no manifesto de operações em lote do S3 para usar no código da função do Lambda, use o seguinte formato JSON codificado por URL. O campo `key` é passado para a função do Lambda como se fosse uma chave de objeto do Amazon S3. Porém, ele pode ser interpretado pela função do Lambda como contendo outros valores ou várias chaves, conforme mostrado nos exemplos a seguir. 

**nota**  
O número máximo de caracteres para o campo `key` no manifesto é 1.024.

**Example – Manifesto que substitui as “chaves do Amazon S3” por strings JSON**  
A versão codificada por URL deve ser fornecida para operações em lote do S3.  

```
amzn-s3-demo-bucket,{"origKey": "object1key", "newKey": "newObject1Key"}
amzn-s3-demo-bucket,{"origKey": "object2key", "newKey": "newObject2Key"}
amzn-s3-demo-bucket,{"origKey": "object3key", "newKey": "newObject3Key"}
```

**Example – Manifesto codificado por URL**  
Essa versão codificada por URL deve ser fornecida para operações em lote do S3. A versão não codificada em URL não funciona.  

```
amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object1key%22%2C%20%22newKey%22%3A%20%22newObject1Key%22%7D
amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object2key%22%2C%20%22newKey%22%3A%20%22newObject2Key%22%7D
amzn-s3-demo-bucket,%7B%22origKey%22%3A%20%22object3key%22%2C%20%22newKey%22%3A%20%22newObject3Key%22%7D
```

**Example função do Lambda com formato de manifesto que grava resultados no relatório de trabalho**  
Esse exemplo de manifesto codificado em URL contém chaves de objeto delimitadas por pipe para que a função do Lambda a seguir analise.  

```
amzn-s3-demo-bucket,object1key%7Clower
amzn-s3-demo-bucket,object2key%7Cupper
amzn-s3-demo-bucket,object3key%7Creverse
amzn-s3-demo-bucket,object4key%7Cdelete
```
Essa função do Lambda mostra como analisar uma tarefa delimitada por pipe que é codificada no manifesto do Operações em Lote do S3. A tarefa indica qual operação de revisão é aplicada ao objeto especificado.  

```
import logging
from urllib import parse
import boto3
from botocore.exceptions import ClientError

logger = logging.getLogger(__name__)
logger.setLevel("INFO")

s3 = boto3.resource("s3")


def lambda_handler(event, context):
    """
    Applies the specified revision to the specified object.

    :param event: The Amazon S3 batch event that contains the ID of the object to
                  revise and the revision type to apply.
    :param context: Context about the event.
    :return: A result structure that Amazon S3 uses to interpret the result of the
             operation.
    """
    # Parse job parameters from Amazon S3 batch operations
    invocation_id = event["invocationId"]
    invocation_schema_version = event["invocationSchemaVersion"]

    results = []
    result_code = None
    result_string = None

    task = event["tasks"][0]
    task_id = task["taskId"]
    # The revision type is packed with the object key as a pipe-delimited string.
    obj_key, revision = parse.unquote_plus(task["s3Key"], encoding="utf-8").split("|")
    bucket_name = task["s3BucketArn"].split(":")[-1]

    logger.info("Got task: apply revision %s to %s.", revision, obj_key)

    try:
        stanza_obj = s3.Bucket(bucket_name).Object(obj_key)
        stanza = stanza_obj.get()["Body"].read().decode("utf-8")
        if revision == "lower":
            stanza = stanza.lower()
        elif revision == "upper":
            stanza = stanza.upper()
        elif revision == "reverse":
            stanza = stanza[::-1]
        elif revision == "delete":
            pass
        else:
            raise TypeError(f"Can't handle revision type '{revision}'.")

        if revision == "delete":
            stanza_obj.delete()
            result_string = f"Deleted stanza {stanza_obj.key}."
        else:
            stanza_obj.put(Body=bytes(stanza, "utf-8"))
            result_string = (
                f"Applied revision type '{revision}' to " f"stanza {stanza_obj.key}."
            )

        logger.info(result_string)
        result_code = "Succeeded"
    except ClientError as error:
        if error.response["Error"]["Code"] == "NoSuchKey":
            result_code = "Succeeded"
            result_string = (
                f"Stanza {obj_key} not found, assuming it was deleted "
                f"in an earlier revision."
            )
            logger.info(result_string)
        else:
            result_code = "PermanentFailure"
            result_string = (
                f"Got exception when applying revision type '{revision}' "
                f"to {obj_key}: {error}."
            )
            logger.exception(result_string)
    finally:
        results.append(
            {
                "taskId": task_id,
                "resultCode": result_code,
                "resultString": result_string,
            }
        )
    return {
        "invocationSchemaVersion": invocation_schema_version,
        "treatMissingKeysAs": "PermanentFailure",
        "invocationId": invocation_id,
        "results": results,
    }
```

## Tutorial Operações em lote do S3
<a name="batch-ops-tutorials-lambda"></a>

O tutorial a seguir apresenta procedimentos completos para algumas tarefas do recurso Operações em Lote com o Lambda. Nesse tutorial, você aprenderá a configurar o Operações em Lote para invocar uma função do Lambda para transcodificação em lote de vídeos armazenados em um bucket de origem do S3. A função do Lambda chama o AWS Elemental MediaConvert para transcodificar os vídeos. 
+ [Tutorial: vídeos de transcodificação em lote com o Operações em Lote do S3](tutorial-s3-batchops-lambda-mediaconvert-video.md)