

# Introdução com exemplos de aplicações e padrões
<a name="example-apps"></a>

Os seguintes recursos podem ser usados para criar e implantar rapidamente aplicações com tecnologia sem servidor que implementam alguns casos de uso comuns do Lambda. Para cada uma das aplicações de exemplo, fornecemos instruções para criar e configurar recursos manualmente usando o Console de gerenciamento da AWS ou para usar o AWS Serverless Application Model com a finalidade de implantar os recursos usando a IaC. Siga as instruções do console para saber mais informações sobre como configurar os recursos individuais da AWS para cada aplicação ou use o AWS SAM para implantar rapidamente os recursos, como você faria em um ambiente de produção.

## Processamento de arquivos
<a name="examples-apps-file"></a>
+ **[Aplicação de criptografia de PDF](file-processing-app.md)**: crie uma aplicação com tecnologia sem servidor que criptografe arquivos PDF quando eles são carregados em um bucket do Amazon Simple Storage Service e os salva em outro bucket, o que é útil para proteger documentos confidenciais durante o upload.
+ **[Aplicação de análise de imagem](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-example-s3.html)**: crie uma aplicação com tecnologia sem servidor que extraia texto de imagens usando o Amazon Rekognition, o que é útil para processamento de documentos, moderação de conteúdo e análise de imagens automatizada.

## Integração de banco de dados
<a name="examples-apps-database"></a>
+ **[Aplicação de fila para banco de dados](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html)**: crie uma aplicação com tecnologia sem servidor que grave as mensagens na fila em um banco de dados do Amazon RDS, o que é útil para processar registros de usuários e lidar com envios de pedidos.
+ **[Manipulador de eventos de banco de dados](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-example-ddb.html)**: crie uma aplicação com tecnologia sem servidor que responda a alterações na tabela do Amazon DynamoDB, o que é útil para registro em log de auditoria, replicação de dados e fluxos de trabalho automatizados.

## Tarefas agendadas
<a name="examples-apps-scheduled"></a>
+ **[Aplicação de manutenção de banco de dados](scheduled-task-app.md)**: crie uma aplicação com tecnologia sem servidor que exclua automaticamente as entradas com mais de 12 meses de uma tabela do Amazon DynamoDB usando um cronograma cron, o que é útil para manutenção automatizada do banco de dados e gerenciamento de ciclo de vida de dados.
+ **[Criar uma regra agendada do EventBridge para funções do Lambda](https://docs.aws.amazon.com/eventbridge/latest/userguide/run-lambda-schedule.html)**: use expressões agendadas em regras do EventBridge para acionar uma função do Lambda segundo um cronograma. Esse formato usa a sintaxe cron e pode ser definido com uma granularidade de um minuto.

## Fluxos de trabalho de longa duração
<a name="examples-apps-workflows"></a>
+ **[Aplicação de processamento de pedidos](order-processing-app.md)**: crie uma aplicação com tecnologia sem servidor usando o Durable Functions que gerencia o atendimento complexo de pedidos, incluindo processamento de pagamentos, verificações de inventário e coordenação de remessas. Este exemplo demonstra como criar fluxos de trabalho que podem ser executados por longos períodos, mantendo o estado.

## Recursos adicionais
<a name="examples-apps-additional-resources"></a>

Use os seguintes recursos para continuar a explorar o Lambda e o desenvolvimento de aplicações com tecnologia sem servidor:
+ **[Serverless Land:](https://serverlessland.com/)**: uma biblioteca de padrões prontos para o uso em desenvolvimento de aplicações com tecnologia sem servidor. Ela ajuda a desenvolver aplicações mais rapidamente usando os serviços da AWS como o Lambda, o API Gateway e o EventBridge. O site oferece soluções pré-compiladas e práticas recomendadas, facilitando o desenvolvimento de sistemas com tecnologia sem servidor.
+ **[Exemplos de aplicações do Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-samples.html)**: aplicações que estão disponíveis no repositório do GitHub para este guia. Esses exemplos demonstram o uso de várias linguagens e serviços da AWS. Cada exemplo de aplicação inclui scripts para fácil implantação e limpeza, e recursos de apoio.
+ **[Exemplos de código para o Lambda usando os SDKs da AWS](https://docs.aws.amazon.com/lambda/latest/dg/service_code_examples.html)**: exemplos que mostram como usar o Lambda com os kits de desenvolvimento de software (SDKs) da AWS. Esses exemplos incluem noções básicas, ações, cenários e contribuições da comunidade da AWS. Os exemplos abrangem operações essenciais, funções de serviços individuais e tarefas específicas usando várias funções ou serviços da AWS.

# Criar uma aplicação de processamento de arquivos com tecnologia sem servidor
<a name="file-processing-app"></a>

Um dos casos de uso mais comuns do Lambda é a realização de tarefas de processamento de arquivos. Por exemplo, você pode usar uma função do Lambda para criar automaticamente arquivos PDF a partir de arquivos HTML ou de imagens, ou para criar miniaturas quando um usuário carrega uma imagem.

Neste exemplo, você cria uma aplicação que criptografa automaticamente os arquivos PDF quando eles são carregados em um bucket do Amazon Simple Storage Service (Amazon S3). Para implementar essa aplicação, você cria os seguintes recursos:
+ Um bucket do S3 no qual os usuários carregam arquivos PDF
+ Uma função do Lambda em Python que lê o arquivo carregado e cria uma versão dele criptografada e protegida por senha
+ Um segundo bucket do S3 no qual o Lambda salva o arquivo criptografado

Você também cria uma política do AWS Identity and Access Management (IAM) para dar à função do Lambda permissão para realizar operações de leitura e gravação nos buckets do S3.

![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/ExampleApps/file_process_resources.png)


**dica**  
Se você nunca trabalhou com o Lambda antes, recomendamos que comece com o tutorial [Criar sua primeira função do Lambda](getting-started.md) antes de criar a aplicação deste exemplo.

É possível implantar a aplicação manualmente criando e configurando os recursos com o Console de gerenciamento da AWS ou a AWS Command Line Interface (AWS CLI). Também é possível implantar a aplicação usando o AWS Serverless Application Model (AWS SAM). O AWS SAM é uma ferramenta de infraestrutura como código (IaC). Usando IaC, você não cria os recursos manualmente, mas os define no código e depois os implanta automaticamente.

Se você quiser saber mais sobre como usar o Lambda com IaC antes de implantar esta aplicação de exemplo, consulte [Usar o Lambda com a infraestrutura como código (IaC)](foundation-iac.md).

## Criar os arquivos de código-fonte da função do Lambda
<a name="file-processing-app-download"></a>

Criar os seguintes arquivos em seu diretório do projeto:
+ `lambda_function.py`: o código de função em Python para a função do Lambda que realiza a criptografia de arquivos
+ `requirements.txt`: um arquivo de manifesto que define as dependências que o código de função em Python exige

Expanda as seções a seguir para visualizar o código e saber mais sobre o perfil de cada arquivo. Para criar os arquivos na máquina local, copie e cole o código abaixo ou baixe os arquivos do [repositório aws-lambda-developer-guide do GitHub](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/file-processing-python).

### Código de função em Python
<a name="file-processing-app-function-code"></a>

Copie e cole o código a seguir em um novo arquivo denominado `lambda_function.py`.

```
from pypdf import PdfReader, PdfWriter
import uuid
import os
from urllib.parse import unquote_plus
import boto3

# Create the S3 client to download and upload objects from S3
s3_client = boto3.client('s3')

def lambda_handler(event, context):
    # Iterate over the S3 event object and get the key for all uploaded files
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = unquote_plus(record['s3']['object']['key']) # Decode the S3 object key to remove any URL-encoded characters
        download_path = f'/tmp/{uuid.uuid4()}.pdf' # Create a path in the Lambda tmp directory to save the file to 
        upload_path = f'/tmp/converted-{uuid.uuid4()}.pdf' # Create another path to save the encrypted file to
        
        # If the file is a PDF, encrypt it and upload it to the destination S3 bucket
        if key.lower().endswith('.pdf'):
            s3_client.download_file(bucket, key, download_path)
            encrypt_pdf(download_path, upload_path)
            encrypted_key = add_encrypted_suffix(key)
            s3_client.upload_file(upload_path, f'{bucket}-encrypted', encrypted_key)

# Define the function to encrypt the PDF file with a password
def encrypt_pdf(file_path, encrypted_file_path):
    reader = PdfReader(file_path)
    writer = PdfWriter()
    
    for page in reader.pages:
        writer.add_page(page)

    # Add a password to the new PDF
    writer.encrypt("my-secret-password")

    # Save the new PDF to a file
    with open(encrypted_file_path, "wb") as file:
        writer.write(file)

# Define a function to add a suffix to the original filename after encryption
def add_encrypted_suffix(original_key):
    filename, extension = original_key.rsplit('.', 1)
    return f'{filename}_encrypted.{extension}'
```

**nota**  
No código deste exemplo, uma senha para o arquivo criptografado (`my-secret-password`) é gravada permanentemente no código da função. Não inclua informações confidenciais, como senhas, no código de função, em uma aplicação em produção. Em vez disso, [crie um segredo do AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) e [use a extensão do Lambda AWS Parameters and Secrets](with-secrets-manager.md) para recuperar suas credenciais na função do Lambda.

O código de função em python contém três funções: a [função de handler](python-handler.md), que o Lambda executa quando a função é invocada, e duas funções separadas denominadas `add_encrypted_suffix` e `encrypt_pdf`, que o handler chama para realizar criptografia de PDF.

Quando a função é invocada pelo Amazon S3, o Lambda passa um argumento *evento* no formato JSON para a função que contém os detalhes do evento que causou a invocação. Nesse caso, as informações incluem o nome do bucket do S3 e as chaves de objeto dos arquivos carregados. Para saber mais sobre o formato do objeto de evento para o Amazon S3, consulte [Processar notificações de eventos do Amazon S3 com o Lambda](with-s3.md).

A função então usa o AWS SDK para Python (Boto3) para baixar os arquivos PDF especificados no objeto de evento para o diretório de armazenamento temporário local antes de criptografá-los usando a biblioteca [https://pypi.org/project/pypdf/](https://pypi.org/project/pypdf/).

Por fim, a função usa o SDK do Boto3 para armazenar o arquivo criptografado no bucket do S3 de destino.

### Arquivo de manifesto `requirements.txt`
<a name="file-processing-app-dependencies"></a>

Copie e cole o código a seguir em um novo arquivo denominado `requirements.txt`.

```
boto3
pypdf
```

Neste exemplo, o código da função tem apenas duas dependências que não fazem parte da biblioteca Python padrão: o SDK para Python (Boto3) e o pacote `pypdf` que a função usa para realizar dos arquivos PDF.

**nota**  
Uma versão do SDK para Python (Boto3) está incluída como parte do runtime do Lambda, portanto, o código seria executado sem adicionar o Boto3 ao pacote de implantação da função. Porém, para manter total controle das dependências da função e evitar possíveis problemas de desalinhamento de versões, a prática recomendada para o Python é incluir todas as dependências da função no pacote de implantação da função. Para saber mais, consulte [Dependências de runtime em Python](python-package.md#python-package-dependencies).

## Implantar a aplicação
<a name="file-processing-app-deploy"></a>

É possível criar e implantar os recursos para a aplicação de exemplo manualmente ou usando o AWS SAM. Em um ambiente de produção, recomendamos o uso de uma ferramenta de IaC, como o AWS SAM, para implantar integralmente as aplicações de tecnologia sem servidor com rapidez, repetidas vezes, sem usar processos manuais.

### Implantar os recursos manualmente
<a name="file-processing-app-deploy-manual"></a>

Para implantar sua aplicação manualmente:
+ Crie os buckets do Amazon S3 de origem e de destino
+ Criar uma função do Lambda que criptografa um arquivo PDF e salva a versão criptografada em um bucket do S3
+ Configure um gatilho do Lambda que invoca a função quando os objetos são carregados no bucket de origem

Antes de começar, certifique-se de que o [Python](https://www.python.org/downloads/) esteja instalado na sua máquina de compilação.

#### Criar dois buckets do S3
<a name="file-processing-app-deploy-manual-create-buckets"></a>

Primeiro, crie dois buckets do S3. O primeiro bucket corresponde ao bucket de origem no qual você vai carregar as imagens. O segundo bucket é usado pelo Lambda para salvar o arquivo criptografado quando você invoca a função.

------
#### [ Console ]

**Para criar os buckets do S3 (console)**

1. Abra a página [Buckets de uso geral](https://console.aws.amazon.com/s3/buckets) do console do Amazon S3.

1. Selecione a Região da AWS mais próxima de sua localização geográfica. É possível alterar a região usando a lista suspensa na parte superior da tela.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/console_region_select.png)

1. Selecione **Criar bucket**.

1. Em **General configuration** (Configuração geral), faça o seguinte:

   1. Em **Tipo de bucket**, certifique-se de que **Uso geral** esteja selecionado.

   1. Em **Bucket name**, insira um nome global exclusivo que atenda às [regras de nomenclatura de buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) do Amazon S3. Os nomes dos buckets podem conter apenas letras minúsculas, números, pontos (.) e hifens (-).

1. Deixe todas as outras opções com seus valores padrão e escolha **Criar bucket**.

1. Repita as etapas 1 a 4 para criar o bucket de destino. Em **Nome do bucket**, insira `amzn-s3-demo-bucket-encrypted`, em que `amzn-s3-demo-bucket` corresponde ao nome do bucket de origem que você acabou de criar.

------
#### [ AWS CLI ]

Antes de começar, certifique-se de que a [AWS CLI esteja instalada](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) em sua máquina de compilação.

**Criar os buckets do Amazon S3 (AWS CLI)**

1. Execute o comando da CLI apresentado a seguir para criar o bucket de origem. O nome escolhido para o bucket deve ser globalmente exclusivo e seguir as [regras de nomeação de bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) para o Amazon S3. Os nomes podem conter somente letras minúsculas, números, pontos (.) e hifens (-). Em `region` e `LocationConstraint`, escolha a [Região da AWS](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) mais próxima de sua localização geográfica.

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-bucket --region us-east-2 \
   --create-bucket-configuration LocationConstraint=us-east-2
   ```

   Posteriormente no tutorial, você deverá criar a função do Lambda na mesma Região da AWS em que o bucket de origem foi criado, portanto, anote a região escolhida.

1. Execute o comando apresentado a seguir para criar o bucket de destino. Para o nome do bucket, você deve usar `amzn-s3-demo-bucket-encrypted`, em que `amzn-s3-demo-bucket` é o nome do bucket de origem criado na etapa 1. Em `region` e `LocationConstraint`, escolha a mesma Região da AWS que você usou ao criar o bucket de origem.

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-bucket-encrypted --region us-east-2 \
   --create-bucket-configuration LocationConstraint=us-east-2
   ```

------

#### Criar uma função de execução
<a name="file-processing-app-deploy-manual-create-execution-role"></a>

Um perfil de execução é um perfil do IAM que concede a uma função do Lambda permissão para acessar os recursos e Serviços da AWS. Para conceder à função acesso de leitura e gravação ao Amazon S3, anexe a [política gerenciada da AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) `AmazonS3FullAccess`.

------
#### [ Console ]

**Para criar uma perfil de execução e anexar a política gerenciada da `AmazonS3FullAccess` (console)**

1. Abra a página [Roles (Funções)](https://console.aws.amazon.com/iam/home/roles) no console do IAM.

1. Selecione **Create role** (Criar função).

1. Em **Trusted entity type**, selecione **AWS service**, e em **Use case**, selecione **Lambda**.

1. Escolha **Próximo**.

1. Para adicionar a política gerenciada do `AmazonS3FullAccess`, faça o seguinte:

   1. Na caixa de pesquisa **Permissions policies**, insira **AmazonS3FullAccess**.

   1. Marque a caixa de seleção ao lado da política.

   1. Escolha **Próximo**.

1. Em **Role details**, insira **LambdaS3Role** em **Role name**.

1. Selecione **Criar perfil**.

------
#### [ AWS CLI ]

**Para criar um perfil de execução e anexar a política gerenciada da `AmazonS3FullAccess` (AWS CLI)**

1. Salve o JSON a seguir em um arquivo denominado `trust-policy.json`. Essa política de confiança permite que o Lambda use as permissões do perfil ao conceder à entidade principal de serviço a permissão `lambda.amazonaws.com` para chamar a ação `AssumeRole` do AWS Security Token Service (AWS STS).  
****  

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

1. No diretório em que você salvou o documento de política de confiança JSON, execute o comando da CLI apresentado a seguir para criar o perfil de execução.

   ```
   aws iam create-role --role-name LambdaS3Role --assume-role-policy-document file://trust-policy.json
   ```

1. Para anexar a política gerenciada da `AmazonS3FullAccess`, execute o comando da CLI a seguir.

   ```
   aws iam attach-role-policy --role-name LambdaS3Role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
   ```

------

#### Crie o pacote de implantação de função
<a name="file-processing-app-deploy-manual-create-function-package"></a>

Para criar sua função, crie um *pacote de implantação* contendo o código de função e as dependências. Para essa aplicação, o código de função usa uma biblioteca separada para a criptografia dos arquivos PDF.

**Para criar o pacote de implantação**

1. Navegue até o diretório do projeto que contém os arquivos `lambda_function.py` e `requirements.txt` que você criou ou baixou anteriormente do GitHub e crie um novo diretório denominado `package`.

1. Instale as dependências especificadas no arquivo `requirements.txt` no diretório `package`executando o comando a seguir.

   ```
   pip install -r requirements.txt --target ./package/
   ```

1. Crie um arquivo .zip contendo o código da aplicação e suas dependências. No Linux ou no MacOS, execute os comandos a seguir na interface da linha de comando.

   ```
   cd package
   zip -r ../lambda_function.zip .
   cd ..
   zip lambda_function.zip lambda_function.py
   ```

    No Windows, use sua ferramenta de zip preferida para criar o arquivo `lambda_function.zip`. Certifique-se de que o arquivo `lambda_function.py` e as pastas que contêm as dependências estejam todos na raiz do arquivo .zip.

Também é possível criar seu pacote de implantação usando um ambiente virtual Python. Consulte [Trabalhar com arquivos .zip para funções do Lambda em Python](python-package.md)

#### Criar a função do Lambda
<a name="file-processing-app-deploy-manual-createfunction"></a>

Agora, você usa o pacote de implantação criado na etapa anterior para implantar a função do Lambda.

------
#### [ Console ]

**Para criar a função (console)**

Para criar a função do Lambda usando o console, primeiro é necessário criar uma função básica contendo algum código “Hello world”. Depois, você substitui esse código por seu próprio código de função carregando o arquivo .zip criado na etapa anterior.

Para garantir que a função não atinja o tempo limite ao criptografar arquivos PDF grandes, você define as configurações de memória e de tempo limite da função. Você também define o formato de log da função como JSON. É necessário configurar os logs no formato JSON ao usar o script de teste fornecido para que ele possa ler o status da invocação da função no CloudWatch Logs para confirmar seu êxito.

1. Abra a [página Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda.

1. Certifique-se de estar trabalhando na mesma Região da AWS em que criou o bucket do S3. É possível alterar a região usando a lista suspensa na parte superior da tela.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/console_region_select.png)

1. Escolha **Create function** (Criar função).

1. Escolha **Author from scratch** (Criar do zero).

1. Em **Basic information** (Informações básicas), faça o seguinte:

   1. Em **Function name** (Nome da função), insira `EncryptPDF`.

   1. Em **Runtime**, selecione **Python 3.12**.

   1. Em **Architecture** (Arquitetura), escolha **x86\$164**.

1. Anexe o perfil de execução que você criou na etapa anterior fazendo o seguinte:

   1. Expandir a seção **Alterar função de execução padrão**.

   1. Selecione **Usar perfil existente**.

   1. Em **Existing role**, selecione seu perfil (`LambdaS3Role`).

1. Escolha a opção **Criar função**.

**Fazer upload do código da função (console)**

1. No painel do **Código-fonte**, escolha **Carregar de**.

1. Escolha o **arquivo .zip**.

1. Escolha **Carregar**.

1. No seletor de arquivos, selecione o arquivo .zip e escolha **Abrir**.

1. Escolha **Salvar**.

**Para configurar a memória e o tempo limite da função (console)**

1. Selecione a guia **Configuração** para a função.

1. No painel **Configuração geral**, escolha **Editar**.

1. Defina **Memória** como 256 MB e **Tempo limite** como 15 segundos.

1. Escolha **Salvar**.

**Para configurar o formato de log (console)**

1. Selecione a guia **Configuração** para a função.

1. Na barra lateral, selecione **Ferramentas de monitoramento e operações**.

1. No painel **Configuração de registro em log**, escolha **Editar**.

1. Em **Configuração do registro em log**, selecione **JSON**.

1. Escolha **Salvar**.

------
#### [ AWS CLI ]

**Criar a função (AWS CLI)**
+ Execute o comando a seguir no diretório que contém o arquivo `lambda_function.zip`. No parâmetro `region`, substitua `us-east-2` pela região em que você criou os buckets do S3.

  ```
  aws lambda create-function --function-name EncryptPDF \
  --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler \
  --runtime python3.12 --timeout 15 --memory-size 256 \
  --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-2 \
  --logging-config LogFormat=JSON
  ```

------

#### Configurar um gatilho do Amazon S3 para invocar a função
<a name="file-processing-app-deploy-manual-configure-s3-trigger"></a>

Para que a função do Lambda seja executada quando você carregar uma imagem no bucket de origem, é necessário configurar um gatilho para a função. É possível configurar o acionador do Amazon S3 usando o console ou a AWS CLI.

**Importante**  
Este procedimento configura o bucket do S3 para invocar a função sempre que um objeto é criado no bucket. Certifique-se de configurar isso somente no bucket de origem. Se a função do Lambda criar objetos no mesmo bucket que a invoca, a função poderá ser [invocada continuamente em um loop](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway). Isso pode resultar em cobranças inesperadas para sua Conta da AWS.

------
#### [ Console ]

**Configurar o acionador do Amazon S3 (console)**

1. Abra a [página de Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda e escolha sua função (`EncryptPDF`).

1. Escolha **Add trigger**.

1. Selecione **S3**.

1. Em **Bucket**, selecione o bucket de origem.

1. Em **Tipos de eventos**, selecione **Todos os eventos de criação de objetos**.

1. Em **Invocação recursiva**, marque a caixa de seleção para confirmar que entende que não é recomendável usar o mesmo bucket do S3 para entrada e saída. Saiba mais sobre padrões de invocação recursiva no Lambda lendo [Recursive patterns that cause run-away Lambda functions](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway) no Serverless Land.

1. Escolha **Adicionar**.

   Quando você cria um acionador usando o console do Lambda, o Lambda cria automaticamente uma [política baseada em recursos](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) para conceder permissão ao serviço selecionado para invocar a função. 

------
#### [ AWS CLI ]

**Configurar o acionador do Amazon S3 (AWS CLI)**

1. Adicione uma [política baseada em recursos](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) à sua função que permita que seu bucket de origem do Amazon S3 invoque sua função quando você adicionar um arquivo. Uma instrução de política baseada em recursos concede permissão a outros Serviços da AWS para invocar sua função. Para conceder permissão ao Amazon S3 para invocar a função, execute o comando da CLI apresentado a seguir. Certifique-se de substituir o parâmetro `source-account` por seu ID da Conta da AWS e usar o nome do bucket de origem.

   ```
   aws lambda add-permission --function-name EncryptPDF \
   --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" \
   --source-arn arn:aws:s3:::amzn-s3-demo-bucket \
   --source-account 123456789012
   ```

   A política que você define com este comando permite que o Amazon S3 invoque a função somente quando uma ação ocorre em seu bucket de origem.
**nota**  
Embora os nomes de bucket do S3 sejam globalmente exclusivos, ao usar políticas baseadas em recursos, é uma prática recomendada especificar que o bucket deve pertencer à sua conta. Isso ocorre porque, se você excluir um bucket, é possível que outra Conta da AWS crie um bucket com o mesmo nome do recurso da Amazon (ARN).

1. Salve o JSON a seguir em um arquivo denominado `notification.json`. Quando aplicado ao bucket de origem, esse JSON configura o bucket para enviar uma notificação à sua função do Lambda sempre que um novo objeto é adicionado. Substitua o número da Conta da AWS e a Região da AWS no ARN da função do Lambda por seu número de conta e sua região.

   ```
   {
   "LambdaFunctionConfigurations": [
       {
         "Id": "EncryptPDFEventConfiguration",
         "LambdaFunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:EncryptPDF",
         "Events": [ "s3:ObjectCreated:Put" ]
       }
     ]
   }
   ```

1. Execute o comando da CLI apresentado a seguir para aplicar as configurações de notificação no arquivo JSON criado ao bucket de origem. Substitua `amzn-s3-demo-bucket` pelo nome do bucket de origem.

   ```
   aws s3api put-bucket-notification-configuration --bucket amzn-s3-demo-bucket \
   --notification-configuration file://notification.json
   ```

   Para saber mais sobre o comando `put-bucket-notification-configuration` e a opção `notification-configuration`, consulte [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html) na *Referência de comandos da CLI da AWS*.

------

### Implantar recursos usando o AWS SAM
<a name="file-processing-app-deploy-sam"></a>

Antes de começar, certifique-se de que o [Docker](https://docs.docker.com/get-docker/) e [a versão mais recente do AWS SAM da CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) estejam instalados na sua máquina de compilação.

1. No diretório do seu projeto, copie e cole o seguinte código em um arquivo chamado `template.yaml`. Substitua os nomes dos buckets de espaço reservado:
   + Para o bucket de origem, substitua `amzn-s3-demo-bucket` por qualquer nome que esteja em conformidade com as [regras de nomenclatura de buckets do S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html).
   + Para o bucket de destino, substitua `amzn-s3-demo-bucket-encrypted` por `<source-bucket-name>-encrypted`, onde `<source-bucket>` é o nome que você escolheu para o bucket de origem.

   ```
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   
   Resources:
     EncryptPDFFunction:
       Type: AWS::Serverless::Function
       Properties:
         FunctionName: EncryptPDF
         Architectures: [x86_64]
         CodeUri: ./
         Handler: lambda_function.lambda_handler
         Runtime: python3.12
         Timeout: 15
         MemorySize: 256
         LoggingConfig:
           LogFormat: JSON
         Policies:
           - AmazonS3FullAccess
         Events:
           S3Event:
             Type: S3
             Properties:
               Bucket: !Ref PDFSourceBucket
               Events: s3:ObjectCreated:*
   
     PDFSourceBucket:
       Type: AWS::S3::Bucket
       Properties:
         BucketName: amzn-s3-demo-bucket
   
     EncryptedPDFBucket:
       Type: AWS::S3::Bucket
       Properties:
         BucketName: amzn-s3-demo-bucket-encrypted
   ```

   O modelo do AWS SAM define os recursos que você cria para a aplicação. Neste exemplo, o modelo define uma função do Lambda usando o tipo `AWS::Serverless::Function` e dois buckets do S3 usando o tipo `AWS::S3::Bucket`. Os nomes dos buckets especificados no modelo são espaços reservados. Antes de implantar a aplicação usando o AWS SAM, você precisa editar o modelo para renomear os buckets com nomes globalmente exclusivos que atendam às [regras de nomenclatura de buckets do S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html). Essa etapa é explicada com mais detalhes em [Implantar recursos usando o AWS SAM](#file-processing-app-deploy-sam).

   A definição do recurso da função do Lambda configura um gatilho para a função usando a propriedade de evento `S3Event`. Esse gatilho faz com que a função seja invocada sempre que um objeto for criado no bucket de origem.

   A definição da função também especifica uma política do AWS Identity and Access Management (IAM) a ser anexada ao [perfil de execução](lambda-intro-execution-role.md) da função. A [política gerenciada da AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) `AmazonS3FullAccess` concede à função as permissões necessárias para ler e gravar objetos no Amazon S3.

1. Execute o comando a seguir no diretório em que você salvou os arquivos `template.yaml`, `lambda_function.py` e `requirements.txt`.

   ```
   sam build --use-container
   ```

   Esse comando reúne os artefatos de compilação da aplicação e os coloca no formato e no local adequados para implantá-los. Especificar a opção `--use-container` compila a função dentro de um contêiner do Docker semelhante ao Lambda. Nós o usamos aqui para que você não precise ter o Python 3.12 instalado na máquina local para que a compilação funcione.

   Durante o processo de compilação, o AWS SAM procura o código da função do Lambda no local que você especificou com a propriedade `CodeUri` no modelo. Neste caso, especificamos o diretório atual como o local (`./`).

   Se houver um arquivo `requirements.txt` presente, o AWS SAM o usará para coletar as dependências especificadas. Por padrão, o AWS SAM cria um pacote de implantação .zip com o código e as dependências da função. Também é possível escolher implantar a função como uma imagem de contêiner usando a propriedade [PackageType](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-packagetype).

1. Para implantar a aplicação e criar os recursos do Lambda e do Amazon S3 especificados no modelo do AWS SAM, execute o comando a seguir.

   ```
   sam deploy --guided
   ```

   Usar o sinalizador `--guided` significa que o AWS SAM mostrará instruções para guiar você no processo de implantação. Para a implantação, aceite as opções padrão pressionando Enter.

Durante o processo de implantação, o AWS SAM cria os seguintes recursos na sua Conta da AWS:
+ Uma [pilha](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html#cfn-concepts-stacks) do CloudFormation chamada `sam-app`
+ Uma função do Lambda com o nome de `EncryptPDF`
+ Dois buckets do S3 com os nomes que você escolheu quando editou o arquivo `template.yaml` do modelo do AWS SAM
+ Um perfil de execução do IAM para sua função com o formato de nome `sam-app-EncryptPDFFunctionRole-2qGaapHFWOQ8`

Quando o AWS SAM termina de criar os recursos, você deve ver a seguinte mensagem:

```
Successfully created/updated stack - sam-app in us-east-2
```

## Testar o aplicativo
<a name="file-processing-app-test"></a>

Para testar a aplicação, carregue um arquivo PDF no bucket de origem e confirme que o Lambda cria uma versão criptografada do arquivo no bucket de destino. Neste exemplo, você pode testar isso manualmente usando o console ou a AWS CLI, ou usando o script de teste fornecido.

Para aplicações em produção, você pode usar os métodos e as técnicas de teste tradicionais, como testes de unidade, para confirmar o funcionamento correto do código da função do Lambda. A prática recomendada também é realizar testes como os do script de teste fornecido que realizam testes de integração com recursos reais baseados na nuvem. Os testes de integração na nuvem confirmam que a infraestrutura foi implantada corretamente e que os eventos fluem entre os diferentes serviços como esperado. Para saber mais, consulte [Como testar funções e aplicações com tecnologia sem servidor](testing-guide.md).

### Testar a aplicação manualmente
<a name="file-processing-app-test-manual"></a>

É possível testar a função manualmente adicionando um arquivo PDF ao bucket de origem do Amazon S3. Quando você adiciona o arquivo ao bucket de origem, a função do Lambda deve ser invocada automaticamente e uma versão criptografada do arquivo deve ser armazenada no bucket de destino.

------
#### [ Console ]

**Para testar a aplicação carregando um arquivo (console)**

1. Para carregar um arquivo PDF no bucket do S3, faça o seguinte:

   1. Abra a página [Buckets](https://console.aws.amazon.com/s3/buckets) do console do Amazon S3 e escolha o bucket de origem.

   1. Escolha **Carregar**.

   1. Escolha **Adicionar arquivos** e use o seletor de arquivo para escolher o arquivo de imagem que você deseja carregar.

   1. Selecione **Abrir** e **Carregar**.

1. Verifique se o Lambda salvou uma versão criptografada do arquivo PDF no bucket de destino fazendo o seguinte:

   1. Retorne para a página [Buckets](https://console.aws.amazon.com/s3/buckets) do console do Amazon S3 e escolha o bucket de destino.

   1. No painel **Objetos**, você deve ver um arquivo com o formato de nome `filename_encrypted.pdf` (onde `filename.pdf` era o nome do arquivo que você enviou para o bucket de origem). Para baixar o PDF criptografado, selecione o arquivo e escolha **Baixar**.

   1. Confirme que você consegue abrir o arquivo baixado com a senha que a função do Lambda usou para protegê-lo (`my-secret-password`).

------
#### [ AWS CLI ]

**Para testar a aplicação carregando um arquivo (AWS CLI)**

1. No diretório que contém o arquivo PDF que você deseja carregar, execute o comando da CLI a seguir. Substitua o parâmetro `--bucket` pelo nome do bucket de origem. Para os parâmetros `--key` e `--body`, use o nome de arquivo do arquivo de teste.

   ```
   aws s3api put-object --bucket amzn-s3-demo-bucket --key test.pdf --body ./test.pdf
   ```

1. Confirme que a função criou uma versão criptografada do arquivo e salvou-a no bucket do S3 de destino. Execute o comando da CLI apresentado a seguir, substituindo `amzn-s3-demo-bucket-encrypted` pelo nome do bucket de destino.

   ```
   aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket-encrypted
   ```

   Se a função for executada com êxito, você visualizará uma saída semelhante à apresentada a seguir. O bucket de destino deve conter um arquivo com o formato de nome `<your_test_file>_encrypted.pdf`, onde `<your_test_file>` é o nome do arquivo que você carregou.

   ```
   {
       "Contents": [
           {
               "Key": "test_encrypted.pdf",
               "LastModified": "2023-06-07T00:15:50+00:00",
               "ETag": "\"7781a43e765a8301713f533d70968a1e\"",
               "Size": 2763,
               "StorageClass": "STANDARD"
           }
       ]
   }
   ```

1. Para baixar o arquivo que o Lambda salvou no bucket de destino, execute o comando da CLI a seguir. Substitua o parâmetro `--bucket` pelo nome do bucket de destino. Para o parâmetro `--key`, use o nome do arquivo `<your_test_file>_encrypted.pdf`, onde `<your_test_file>` é o nome do arquivo de teste que você carregou.

   ```
   aws s3api get-object --bucket amzn-s3-demo-bucket-encrypted --key test_encrypted.pdf my_encrypted_file.pdf
   ```

   Esse comando baixa o arquivo para o diretório atual e salva-o como `my_encrypted_file.pdf`.

1. Confirme que você consegue abrir o arquivo baixado com a senha que a função do Lambda usou para protegê-lo (`my-secret-password`).

------

### Testar a aplicação com o script automatizado
<a name="file-processing-app-test-auto"></a>

Crie os seguintes arquivos em seu diretório do projeto:
+ `test_pdf_encrypt.py`: um script de teste que você pode usar para testar automaticamente a aplicação
+ `pytest.ini`: um arquivo de configuração para o script de teste

Expanda as seções a seguir para visualizar o código e saber mais sobre o perfil de cada arquivo.

#### Script de teste automatizado
<a name="file-processing-app-test-script"></a>

Copie e cole o código a seguir em um novo arquivo denominado `test_pdf_encrypt.py`. Certifique-se de substituir os nomes dos buckets de espaço reservado:
+ Na função `test_source_bucket_available`, substitua `amzn-s3-demo-bucket` pelo nome do bucket de origem.
+ Na função `test_encrypted_file_in_bucket`, substitua `amzn-s3-demo-bucket-encrypted` por `source-bucket-encrypted`, onde `source-bucket>` é o nome do bucket de origem.
+ Na função `cleanup`, substitua `amzn-s3-demo-bucket` pelo nome do bucket de origem e substitua `amzn-s3-demo-bucket-encrypted` pelo nome do seu bucket de destino.

```
import boto3
import json
import pytest
import time
import os

@pytest.fixture
def lambda_client():
    return boto3.client('lambda')
    
@pytest.fixture
def s3_client():
    return boto3.client('s3')

@pytest.fixture
def logs_client():
    return boto3.client('logs')

@pytest.fixture(scope='session')
def cleanup():
    # Create a new S3 client for cleanup
    s3_client = boto3.client('s3')

    yield
    # Cleanup code will be executed after all tests have finished

    # Delete test.pdf from the source bucket
    source_bucket = 'amzn-s3-demo-bucket'
    source_file_key = 'test.pdf'
    s3_client.delete_object(Bucket=source_bucket, Key=source_file_key)
    print(f"\nDeleted {source_file_key} from {source_bucket}")

    # Delete test_encrypted.pdf from the destination bucket
    destination_bucket = 'amzn-s3-demo-bucket-encrypted'
    destination_file_key = 'test_encrypted.pdf'
    s3_client.delete_object(Bucket=destination_bucket, Key=destination_file_key)
    print(f"Deleted {destination_file_key} from {destination_bucket}")
        

@pytest.mark.order(1)
def test_source_bucket_available(s3_client):
    s3_bucket_name = 'amzn-s3-demo-bucket'
    file_name = 'test.pdf'
    file_path = os.path.join(os.path.dirname(__file__), file_name)

    file_uploaded = False
    try:
        s3_client.upload_file(file_path, s3_bucket_name, file_name)
        file_uploaded = True
    except:
        print("Error: couldn't upload file")

    assert file_uploaded, "Could not upload file to S3 bucket"

    

@pytest.mark.order(2)
def test_lambda_invoked(logs_client):

    # Wait for a few seconds to make sure the logs are available
    time.sleep(5)

    # Get the latest log stream for the specified log group
    log_streams = logs_client.describe_log_streams(
        logGroupName='/aws/lambda/EncryptPDF',
        orderBy='LastEventTime',
        descending=True,
        limit=1
    )

    latest_log_stream_name = log_streams['logStreams'][0]['logStreamName']

    # Retrieve the log events from the latest log stream
    log_events = logs_client.get_log_events(
        logGroupName='/aws/lambda/EncryptPDF',
        logStreamName=latest_log_stream_name
    )

    success_found = False
    for event in log_events['events']:
        message = json.loads(event['message'])
        status = message.get('record', {}).get('status')
        if status == 'success':
            success_found = True
            break

    assert success_found, "Lambda function execution did not report 'success' status in logs."

@pytest.mark.order(3)
def test_encrypted_file_in_bucket(s3_client):
    # Specify the destination S3 bucket and the expected converted file key
    destination_bucket = 'amzn-s3-demo-bucket-encrypted'
    converted_file_key = 'test_encrypted.pdf'

    try:
        # Attempt to retrieve the metadata of the converted file from the destination S3 bucket
        s3_client.head_object(Bucket=destination_bucket, Key=converted_file_key)
    except s3_client.exceptions.ClientError as e:
        # If the file is not found, the test will fail
        pytest.fail(f"Converted file '{converted_file_key}' not found in the destination bucket: {str(e)}")

def test_cleanup(cleanup):
    # This test uses the cleanup fixture and will be executed last
    pass
```

O script de teste automatizado executa três funções de teste para confirmar que a aplicação está funcionando corretamente:
+ O teste `test_source_bucket_available` confirma que o bucket de origem foi criado com êxito carregando nele um arquivo PDF de teste.
+ O teste `test_lambda_invoked` interroga o último fluxo de logs do CloudWatch Logs para a função para confirmar que, quando você carregou o arquivo de teste, a função do Lambda foi executada e reportada como bem-sucedida.
+ O teste `test_encrypted_file_in_bucket` confirma que o bucket de destino contém o arquivo `test_encrypted.pdf` criptografado.

Após a execução de todos esses testes, o script executa uma etapa adicional de limpeza para excluir os arquivos `test.pdf` e `test_encrypted.pdf` dos buckets de origem e de destino.

Como no modelo do AWS SAM, os nomes de bucket especificados nesse arquivo são espaços reservados. Antes de executar o teste, você precisa editar esse arquivo com os nomes reais dos buckets da aplicação. Essa etapa é explicada com mais detalhes em [Testar a aplicação com o script automatizado](#file-processing-app-test-auto)

#### Arquivo de configuração do script de teste
<a name="file-processing-app-test-config"></a>

Copie e cole o código a seguir em um novo arquivo denominado `pytest.ini`.

```
[pytest]
markers =
    order: specify test execution order
```

Isso é necessário para especificar a ordem em que os testes do script `test_pdf_encrypt.py` são executados.

Para executar os testes, faça o seguinte:

1. Certifique-se de que o módulo `pytest` esteja instalado no seu ambiente local. É possível instalar o `pytest` executando o seguinte comando:

   ```
   pip install pytest
   ```

1. Salve um arquivo PDF denominado `test.pdf` no diretório que contém os arquivos `test_pdf_encrypt.py` e `pytest.ini`.

1. Abra um terminal ou um programa shell e execute o comando a seguir no diretório que contém os arquivos de teste.

   ```
   pytest -s -v
   ```

   Quando o teste for concluído, você verá uma saída como a seguinte:

   ```
   ============================================================== test session starts =========================================================
   platform linux -- Python 3.12.2, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3
   cachedir: .pytest_cache
   hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/home/pdf_encrypt_app/.hypothesis/examples')
   Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type>
   rootdir: /home/pdf_encrypt_app, configfile: pytest.ini
   plugins: anyio-3.7.1, hypothesis-6.70.0, localserver-0.7.1, random-order-1.1.0
   collected 4 items
   
   test_pdf_encrypt.py::test_source_bucket_available PASSED
   test_pdf_encrypt.py::test_lambda_invoked PASSED
   test_pdf_encrypt.py::test_encrypted_file_in_bucket PASSED
   test_pdf_encrypt.py::test_cleanup PASSED
   Deleted test.pdf from amzn-s3-demo-bucket
   Deleted test_encrypted.pdf from amzn-s3-demo-bucket-encrypted
   
   
   =============================================================== 4 passed in 7.32s ==========================================================
   ```

## Próximas etapas
<a name="file-processing-app-next-steps"></a>

Agora que você criou esta aplicação de exemplo, pode usar o código fornecido como base para criar outros tipos de aplicação de processamento de arquivos. Modifique o código no arquivo `lambda_function.py` para implementar a lógica de processamento de arquivos para seu caso de uso.

Muitos casos de uso típicos de processamento de arquivos envolvem processamento de imagens. Ao usar o Python, as bibliotecas de processamento de imagens mais populares, como a [pillow](https://pypi.org/project/pillow/), normalmente contêm componentes em C ou C\$1\$1. Para garantir que o pacote de implantação da função seja compatível com o ambiente de execução do Lambda, é importante usar o binário de distribuição do fonte correto.

Ao implantar os recursos com o AWS SAM, você precisa tomar algumas medidas adicionais para incluir a distribuição do fonte correto no pacote de implantação. Como o AWS SAM não instala dependências para uma plataforma diferente da plataforma da máquina de compilação, especificar a distribuição do fonte correto (arquivo `.whl`) no arquivo `requirements.txt` não funcionará se sua máquina de compilação usar um sistema operacional ou uma arquitetura diferente do ambiente de execução do Lambda. Em vez disso, você deve realizar um dos seguintes procedimentos:
+ Use a opção `--use-container` ao executar `sam build`. Quando você especifica essa opção, o AWS SAM baixa uma imagem de base de contêiner compatível com o ambiente de execução do Lambda e cria o pacote de implantação da função em um contêiner do Docker usando essa imagem. Para saber mais, consulte [Compilando uma função do Lambda dentro de um contêiner fornecido](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-build.html#using-sam-cli-build-options-container).
+ Compile você mesmo o pacote de implantação .zip da função usando o binário de distribuição do fonte correto e salve o arquivo.zip no diretório que especificar como `CodeUri` no AWS SAM modelo. Para saber mais sobre a compilação de pacotes de implantação .zip para Python usando distribuições binárias, consulte [Criar um pacote de implantação .zip com dependências](python-package.md#python-package-create-dependencies) e [Criar pacotes de implantação .zip com bibliotecas nativas](python-package.md#python-package-native-libraries).

# Criação de uma aplicação para executar uma manutenção agendada no banco de dados
<a name="scheduled-task-app"></a>

É possível usar o AWS Lambda para substituir processos agendados, como backups automáticos do sistema, conversões de arquivos e tarefas de manutenção. Neste exemplo, você criará uma aplicação com tecnologia sem servidor que realiza uma manutenção agendada em uma tabela do DynamoDB ao excluir entradas antigas. A aplicação usa o Agendador do EventBridge para invocar uma função do Lambda com um agendamento cron. Quando invocada, a função consulta a tabela em busca de itens com mais de um ano e os exclui. A função registra em log cada item excluído no CloudWatch Logs.

Para realizar a implementação deste exemplo, primeiro crie uma tabela do DynamoDB e a preencha com dados de teste que a função consultará. Em seguida, crie uma função do Lambda em Python com um acionador do Agendador do EventBridge e um perfil de execução do IAM que conceda à função permissão para ler e excluir itens da tabela.

![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/ExampleApps/cron_app.png)


**dica**  
Caso você seja iniciante no Lambda, recomendamos que conclua o tutorial [Criar sua primeira função do Lambda](getting-started.md) antes de realizar a criação desta aplicação de exemplo.

É possível implantar a aplicação manualmente ao criar e ao configurar recursos com o Console de gerenciamento da AWS. Também é possível implantar a aplicação usando o AWS Serverless Application Model (AWS SAM). O AWS SAM é uma ferramenta de infraestrutura como código (IaC). Usando IaC, você não cria os recursos manualmente, mas os define no código e depois os implanta automaticamente.

Se você quiser saber mais sobre como usar o Lambda com IaC antes de implantar esta aplicação de exemplo, consulte [Usar o Lambda com a infraestrutura como código (IaC)](foundation-iac.md).

## Pré-requisitos
<a name="scheduled-task-app-prereqs"></a>

Antes de criar a aplicação de exemplo, certifique-se de que as ferramentas de linha de comando e os programas necessários estejam instalados.
+ **Python**

  Para preencher a tabela do DynamoDB que você cria para testar a aplicação, este exemplo usa um script em Python e um arquivo CSV para gravar os dados na tabela. Certifique-se de que você tenha o Python na versão 3.8, ou em versões superiores, instalado em sua máquina.
+ **AWS SAM CLI**

  Se você deseja criar a tabela do DynamoDB e implantar a aplicação de exemplo usando o AWS SAM, é necessário instalar a CLI do AWS SAM. Siga as [instruções de instalação](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) apresentadas no *Guia do usuário do AWS SAM*.
+ **AWS CLI**

  Para usar o script em Python fornecido para preencher a tabela de teste, é necessário ter a AWS CLI instalada e configurada. Isso ocorre porque o script usa o AWS SDK para Python (Boto3), que precisa acessar as credenciais do AWS Identity and Access Management (IAM). Além disso, a AWS CLI deve estar instalada para que você possa implantar recursos usando o AWS SAM. Instale a CLI seguindo as [instruções de instalação](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) apresentadas no *Guia do usuário da AWS Command Line Interface*.
+ **Docker**

  Para realizar a implantação da aplicação usando o AWS SAM, também é necessário que o Docker esteja instalado na sua máquina de compilação. Siga as instruções apresentadas em [Install Docker Engine](https://docs.docker.com/engine/install/) no site de documentação do Docker.

## Baixar os arquivos da aplicação de exemplo
<a name="scheduled-task-app-download"></a>

Para criar o banco de dados de exemplo e a aplicação de manutenção agendada, é necessário criar os seguintes arquivos em seu diretório de projeto:

**Exemplos de arquivos de banco de dados**
+ `template.yaml`: um modelo do AWS SAM que pode ser usado para criar a tabela do DynamoDB
+ `sample_data.csv`: um arquivo CSV que contém dados de amostra para serem carregados em sua tabela
+ `load_sample_data.py`: um script em Python que grava os dados do arquivo CSV na tabela

**Arquivos da aplicação de manutenção agendada**
+ `lambda_function.py`: o código da função em Python para a função do Lambda que executa a manutenção do banco de dados
+ `requirements.txt`: um arquivo de manifesto que define as dependências que o código de função em Python exige
+ `template.yaml`: um modelo do AWS SAM que você pode usar para implantar a aplicação

**Arquivo de teste**
+ `test_app.py`: um script em Python que faz a verificação da tabela e confirma o funcionamento correto da sua função ao listar todos os registros com mais de um ano

Expanda as seções a seguir para visualizar o código e saber mais sobre o papel de cada arquivo na criação e no teste da aplicação. Para criar os arquivos em sua máquina local, copie e cole o código apresentado abaixo.

### Modelo do AWS SAM (exemplo de tabela do DynamoDB)
<a name="scheduled-task-app-table-yaml"></a>

Copie e cole o código a seguir em um novo arquivo denominado `template.yaml`.

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for DynamoDB Table with Order_number as Partition Key and Date as Sort Key

Resources:
  MyDynamoDBTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Properties:
      TableName: MyOrderTable
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: Order_number
          AttributeType: S
        - AttributeName: Date
          AttributeType: S
      KeySchema:
        - AttributeName: Order_number
          KeyType: HASH
        - AttributeName: Date
          KeyType: RANGE
      SSESpecification:
        SSEEnabled: true
      GlobalSecondaryIndexes:
        - IndexName: Date-index
          KeySchema:
            - AttributeName: Date
              KeyType: HASH
          Projection:
            ProjectionType: ALL
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: true

Outputs:
  TableName:
    Description: DynamoDB Table Name
    Value: !Ref MyDynamoDBTable
  TableArn:
    Description: DynamoDB Table ARN
    Value: !GetAtt MyDynamoDBTable.Arn
```

**nota**  
Os modelos do AWS SAM usam uma convenção de nomenclatura padrão, que é `template.yaml`. Neste exemplo, você terá dois arquivos de modelo: um para criar o banco de dados de exemplo e outro para criar a aplicação em si. Salve-os em subdiretórios separados na pasta de projeto.

Este modelo do AWS SAM define o recurso da tabela do DynamoDB que você cria para testar a aplicação. A tabela usa uma chave primária, chamada `Order_number`, com uma chave de classificação, chamada `Date`. Para que a função do Lambda localize itens diretamente pela data, também definimos um [índice secundário global](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html), chamado `Date-index`.

Para saber mais sobre como criar e configurar uma tabela do DynamoDB usando o recurso `AWS::DynamoDB::Table`, consulte [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html) no *Guia do usuário do AWS CloudFormation*.

### Arquivo de dados do banco de dados de amostra
<a name="scheduled-task-app-csv-file"></a>

Copie e cole o código a seguir em um novo arquivo denominado `sample_data.csv`.

```
Date,Order_number,CustomerName,ProductID,Quantity,TotalAmount
2023-09-01,ORD001,Alejandro Rosalez,PROD123,2,199.98
2023-09-01,ORD002,Akua Mansa,PROD456,1,49.99
2023-09-02,ORD003,Ana Carolina Silva,PROD789,3,149.97
2023-09-03,ORD004,Arnav Desai,PROD123,1,99.99
2023-10-01,ORD005,Carlos Salazar,PROD456,2,99.98
2023-10-02,ORD006,Diego Ramirez,PROD789,1,49.99
2023-10-03,ORD007,Efua Owusu,PROD123,4,399.96
2023-10-04,ORD008,John Stiles,PROD456,2,99.98
2023-10-05,ORD009,Jorge Souza,PROD789,3,149.97
2023-10-06,ORD010,Kwaku Mensah,PROD123,1,99.99
2023-11-01,ORD011,Li Juan,PROD456,5,249.95
2023-11-02,ORD012,Marcia Oliveria,PROD789,2,99.98
2023-11-03,ORD013,Maria Garcia,PROD123,3,299.97
2023-11-04,ORD014,Martha Rivera,PROD456,1,49.99
2023-11-05,ORD015,Mary Major,PROD789,4,199.96
2023-12-01,ORD016,Mateo Jackson,PROD123,2,199.99
2023-12-02,ORD017,Nikki Wolf,PROD456,3,149.97
2023-12-03,ORD018,Pat Candella,PROD789,1,49.99
2023-12-04,ORD019,Paulo Santos,PROD123,5,499.95
2023-12-05,ORD020,Richard Roe,PROD456,2,99.98
2024-01-01,ORD021,Saanvi Sarkar,PROD789,3,149.97
2024-01-02,ORD022,Shirley Rodriguez,PROD123,1,99.99
2024-01-03,ORD023,Sofia Martinez,PROD456,4,199.96
2024-01-04,ORD024,Terry Whitlock,PROD789,2,99.98
2024-01-05,ORD025,Wang Xiulan,PROD123,3,299.97
```

Este arquivo contém alguns dados de teste de exemplo para preencher a tabela do DynamoDB em um formato padrão de valores separados por vírgula (CSV).

### Script em Python para carregar dados de amostra
<a name="scheduled-task-app-load-script"></a>

Copie e cole o código a seguir em um novo arquivo denominado `load_sample_data.py`.

```
import boto3
import csv
from decimal import Decimal

# Initialize the DynamoDB client
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('MyOrderTable') 
print("DDB client initialized.")

def load_data_from_csv(filename):
    with open(filename, 'r') as file:
        csv_reader = csv.DictReader(file)
        for row in csv_reader:
            item = {
                'Order_number': row['Order_number'],
                'Date': row['Date'],
                'CustomerName': row['CustomerName'],
                'ProductID': row['ProductID'],
                'Quantity': int(row['Quantity']),
                'TotalAmount': Decimal(str(row['TotalAmount']))
            }
            table.put_item(Item=item)
            print(f"Added item: {item['Order_number']} - {item['Date']}")

if __name__ == "__main__":
    load_data_from_csv('sample_data.csv')
    print("Data loading completed.")
```

Primeiro, este script em Python usa o AWS SDK para Python (Boto3) para criar uma conexão com a tabela do DynamoDB. Em seguida, ele itera sobre cada linha no arquivo CSV de dados de exemplo, cria um item usando essa linha e grava o item na tabela do DynamoDB usando o SDK para Boto3.

### Código de função em Python
<a name="scheduled-task-app-function-code"></a>

Copie e cole o código a seguir em um novo arquivo denominado `lambda_function.py`.

```
import boto3
from datetime import datetime, timedelta
from boto3.dynamodb.conditions import Key, Attr
import logging

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

def lambda_handler(event, context):
    # Initialize the DynamoDB client
    dynamodb = boto3.resource('dynamodb')
    
    # Specify the table name
    table_name = 'MyOrderTable'
    table = dynamodb.Table(table_name)
    
    # Get today's date
    today = datetime.now()
    
    # Calculate the date one year ago
    one_year_ago = (today - timedelta(days=365)).strftime('%Y-%m-%d')
    
    # Scan the table using a global secondary index
    response = table.scan(
        IndexName='Date-index',
        FilterExpression='#date < :one_year_ago',
        ExpressionAttributeNames={
            '#date': 'Date'
        },
        ExpressionAttributeValues={
            ':one_year_ago': one_year_ago
        }
    )
    
     # Delete old items
    with table.batch_writer() as batch:
        for item in response['Items']:
            Order_number = item['Order_number']
            batch.delete_item(
                Key={
                    'Order_number': Order_number,
                    'Date': item['Date']
                }
            )
            logger.info(f'deleted order number {Order_number}')
    
    # Check if there are more items to scan
    while 'LastEvaluatedKey' in response:
        response = table.scan(
            IndexName='DateIndex',
            FilterExpression='#date < :one_year_ago',
            ExpressionAttributeNames={
                '#date': 'Date'
            },
            ExpressionAttributeValues={
                ':one_year_ago': one_year_ago
            },
            ExclusiveStartKey=response['LastEvaluatedKey']
        )
        
        # Delete old items
        with table.batch_writer() as batch:
            for item in response['Items']:
                batch.delete_item(
                    Key={
                        'Order_number': item['Order_number'],
                        'Date': item['Date']
                    }
                )
    
    return {
        'statusCode': 200,
        'body': 'Cleanup completed successfully'
    }
```

O código da função em Python contém a [função do manipulador](python-handler.md) (`lambda_handler`) que o Lambda executa quando a função é invocada.

Quando a função é invocada pelo Agendador do EventBridge, ela usa o AWS SDK para Python (Boto3) para criar uma conexão com a tabela do DynamoDB na qual a tarefa de manutenção agendada será executada. Em seguida, a função usa a biblioteca `datetime` do Python para calcular a data de um ano atrás, antes de realizar a verificação da tabela em busca de itens mais antigos e excluí-los.

Lembre-se de que as respostas das operações de consulta e de verificação do DynamoDB são limitadas a um tamanho máximo de 1 MB. Se a resposta for maior que 1 MB, o DynamoDB fará a paginação dos dados e retornará um elemento `LastEvaluatedKey` na resposta. Para garantir que nossa função processe todos os registros apresentados na tabela, verificamos a presença dessa chave e continuamos executando verificações na tabela a partir da última posição avaliada até que toda a tabela tenha sido verificada.

### Arquivo de manifesto `requirements.txt`
<a name="scheduled-task-app-dependencies"></a>

Copie e cole o código a seguir em um novo arquivo denominado `requirements.txt`.

```
boto3
```

Neste exemplo, o código da função tem somente uma dependência que não faz parte da biblioteca padrão do Python, o SDK para Python (Boto3), que a função usa para realizar verificações e excluir itens da tabela do DynamoDB.

**nota**  
Uma versão do SDK para Python (Boto3) está incluída como parte do runtime do Lambda, portanto, o código seria executado sem adicionar o Boto3 ao pacote de implantação da função. Porém, para manter total controle das dependências da função e evitar possíveis problemas de desalinhamento de versões, a prática recomendada para o Python é incluir todas as dependências da função no pacote de implantação da função. Para saber mais, consulte [Dependências de runtime em Python](python-package.md#python-package-dependencies).

### Modelo do AWS SAM (aplicação de manutenção agendada)
<a name="scheduled-task-app-table-yaml"></a>

Copie e cole o código a seguir em um novo arquivo denominado `template.yaml`.

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda function and EventBridge Scheduler rule

Resources:
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: ScheduledDBMaintenance
      CodeUri: ./
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      Events:
        ScheduleEvent:
          Type: ScheduleV2
          Properties:
            ScheduleExpression: cron(0 3 1 * ? *)
            Description: Run on the first day of every month at 03:00 AM
      Policies:
        - CloudWatchLogsFullAccess
        - Statement:
            - Effect: Allow
              Action:
                - dynamodb:Scan
                - dynamodb:BatchWriteItem
              Resource: !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/MyOrderTable'

  LambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${MyLambdaFunction}
      RetentionInDays: 30

Outputs:
  LambdaFunctionName:
    Description: Lambda Function Name
    Value: !Ref MyLambdaFunction
  LambdaFunctionArn:
    Description: Lambda Function ARN
    Value: !GetAtt MyLambdaFunction.Arn
```

**nota**  
Os modelos do AWS SAM usam uma convenção de nomenclatura padrão, que é `template.yaml`. Neste exemplo, você terá dois arquivos de modelo: um para criar o banco de dados de exemplo e outro para criar a aplicação em si. Salve-os em subdiretórios separados na pasta de projeto.

Este modelo do AWS SAM define os recursos para a aplicação. A função do Lambda é definida usando o recurso `AWS::Serverless::Function`. O agendamento do Agendador do EventBridge e o acionador para invocar a função do Lambda são criados ao usar a propriedade `Events` desse recurso, com o tipo `ScheduleV2`. Para saber mais informações sobre como definir agendamentos do Agendador do EventBridge em modelos do AWS SAM, consulte [ScheduleV2](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-schedulev2.html) no *Guia do desenvolvedor do AWS Serverless Application Model*.

Além da função do Lambda e do agendamento do Agendador do EventBridge, também definimos um grupo de logs do CloudWatch para que a função envie registros dos itens excluídos.

### Script de teste
<a name="scheduled-task-app-test-script"></a>

Copie e cole o código a seguir em um novo arquivo denominado `test_app.py`.

```
import boto3
from datetime import datetime, timedelta
import json

# Initialize the DynamoDB client
dynamodb = boto3.resource('dynamodb')

# Specify your table name
table_name = 'YourTableName'
table = dynamodb.Table(table_name)

# Get the current date
current_date = datetime.now()

# Calculate the date one year ago
one_year_ago = current_date - timedelta(days=365)

# Convert the date to string format (assuming the date in DynamoDB is stored as a string)
one_year_ago_str = one_year_ago.strftime('%Y-%m-%d')

# Scan the table
response = table.scan(
    FilterExpression='#date < :one_year_ago',
    ExpressionAttributeNames={
        '#date': 'Date'
    },
    ExpressionAttributeValues={
        ':one_year_ago': one_year_ago_str
    }
)

# Process the results
old_records = response['Items']

# Continue scanning if we have more items (pagination)
while 'LastEvaluatedKey' in response:
    response = table.scan(
        FilterExpression='#date < :one_year_ago',
        ExpressionAttributeNames={
            '#date': 'Date'
        },
        ExpressionAttributeValues={
            ':one_year_ago': one_year_ago_str
        },
        ExclusiveStartKey=response['LastEvaluatedKey']
    )
    old_records.extend(response['Items'])

for record in old_records:
    print(json.dumps(record))

# The total number of old records should be zero.
print(f"Total number of old records: {len(old_records)}")
```

Este script de teste usa o AWS SDK para Python (Boto3) para criar uma conexão com a tabela do DynamoDB e realizar a verificação de itens com mais de um ano. Para confirmar se a função do Lambda foi executada com êxito, ao final do teste, solicite que a função realize a impressão do número de registros com mais de um ano ainda presentes na tabela. Se a função do Lambda obteve êxito, o número de registros antigos na tabela deverá ser zero. 

## Criação e preenchimento da tabela de exemplo do DynamoDB
<a name="scheduled-task-app-create-table"></a>

Para testar a aplicação de manutenção agendada, primeiro, crie uma tabela do DynamoDB e preencha-a com alguns dados de amostra. É possível criar a tabela manualmente usando o Console de gerenciamento da AWS ou usando o AWS SAM. Recomendamos o uso do AWS SAM para criar e configurar a tabela rapidamente usando alguns comandos da AWS CLI.

------
#### [ Console ]

**Para criar uma tabela do DynamoDB**

1. Abra a [página Tables (Tabelas) no console do DynamoDB](https://console.aws.amazon.com/dynamodbv2/home#tables).

1. Escolha **Criar tabela**.

1. Para criar a tabela, faça o seguinte:

   1. Em **Detalhes da tabela**, no campo **Nome da tabela**, insira **MyOrderTable**.

   1. Em **Chave de partição**, insira **Order\$1number** e mantenha o tipo definido como **String**.

   1. Em **Chave de classificação**, insira **Date** e mantenha o tipo definido como **String**.

   1. Mantenha as **Configurações da tabela** em **Configurações padrão** e selecione **Criar tabela**.

1. Assim que a criação da tabela for concluída e o **Status** estiver sendo mostrado como **Ativa**, crie um índice secundário global (GSI) conforme as etapas apresentadas a seguir. A aplicação usará esse GSI para pesquisar itens diretamente pela data e determinar quais devem ser excluídos.

   1. Escolha **MyOrderTable** na lista de tabelas.

   1. Selecione a guia **Índices**.

   1. Em **Índices secundários globais**, escolha **Criar índice**.

   1. Em **Detalhes do índice**, insira **Date** a **chave de partição** e deixe o **Tipo de dados** definido como **String**.

   1. Em **Nome do índice**, insira **Date-index**.

   1. Mantenha todos os outros parâmetros com os valores padrão definidos, role até o final da página e selecione **Criar índice**.

------
#### [ AWS SAM ]

**Para criar uma tabela do DynamoDB**

1. Acesse a pasta em que você salvou o arquivo `template.yaml` para a tabela do DynamoDB. Lembre-se de que este exemplo utiliza dois arquivos `template.yaml`. Verifique se os arquivos estão salvos em subpastas separadas e se você está na pasta correta que contém o modelo para criar a tabela do DynamoDB.

1. Execute o comando a seguir.

   ```
   sam build
   ```

   Este comando reúne os artefatos de compilação para os recursos que você deseja implantar e os organiza no formato e no local apropriados para a implantação.

1. Para criar o recurso do DynamoDB especificado no arquivo `template.yaml`, execute o comando apresentado a seguir.

   ```
   sam deploy --guided
   ```

   Usar o sinalizador `--guided` significa que o AWS SAM mostrará instruções para guiar você no processo de implantação. Para essa implantação, insira **cron-app-test-db** como `Stack name` e, em seguida, pressione Enter para aceitar os valores padrão para todas as outras opções.

   Quando o AWS SAM concluir a criação do recurso do DynamoDB, a mensagem apresentada a seguir deverá ser visualizada.

   ```
   Successfully created/updated stack - cron-app-test-db in us-west-2
   ```

1. Além disso, é possível confirmar se a tabela do DynamoDB foi criada ao abrir a página de [Tabelas](https://console.aws.amazon.com/dynamodbv2/home#tables) no console do DynamoDB. Você deverá ver uma tabela chamada `MyOrderTable`.

------

Após criar a tabela, adicione alguns dados de amostra para testar a aplicação. O arquivo CSV `sample_data.csv`, que você efetuou o download anteriormente, contém várias entradas de exemplo, compostas por números de pedidos, datas, informações de clientes e de pedidos. Use o script em Python fornecido, `load_sample_data.py`, para adicionar esses dados à sua tabela.

**Para adicionar os dados de amostra à tabela**

1. Acesse o diretório que contém os arquivos `sample_data.csv` e `load_sample_data.py`. Se esses arquivos estiverem em diretórios separados, mova-os para que fiquem salvos no mesmo local.

1. Crie um ambiente virtual para Python a fim de executar o script ao executar o comando apresentado a seguir. Recomendamos o uso de um ambiente virtual, pois em uma etapa posterior será necessário instalar o AWS SDK para Python (Boto3).

   ```
   python -m venv venv
   ```

1. Ative o ambiente virtual ao executar o comando apresentado a seguir.

   ```
   source venv/bin/activate
   ```

1. Instale o SDK para Python (Boto3) no ambiente virtual ao executar o comando apresentado abaixo. O script usa essa biblioteca para se conectar à sua tabela do DynamoDB e adicionar os itens.

   ```
   pip install boto3
   ```

1. Execute o script para preencher a tabela ao executar o comando apresentado a seguir.

   ```
   python load_sample_data.py
   ```

   Se o script for executado com êxito, cada item será exibido no console à medida que for carregado, seguido da mensagem `Data loading completed`.

1. Desative o ambiente virtual ao executar o comando apresentado a seguir.

   ```
   deactivate
   ```

1. É possível verificar se os dados foram carregados na sua tabela do DynamoDB ao seguir estas etapas:

   1. Abra a página [Explorar itens](https://console.aws.amazon.com/dynamodbv2/home#item-explorer) no console do DynamoDB e selecione sua tabela (`MyOrderTable`).

   1. No painel **Itens retornados**, você deverá visualizar os 25 itens do arquivo CSV que o script adicionou à tabela.

## Criação da aplicação de manutenção agendada
<a name="scheduled-task-app-create-app"></a>

É possível criar e implantar os recursos desta aplicação de exemplo, etapa por etapa, ao usar o Console de gerenciamento da AWS ou o AWS SAM. Em um ambiente de produção, recomendamos o uso de uma ferramenta de infraestrutura como código (IaC), como o AWS SAM, para implantar repetidamente aplicações com tecnologia sem servidor sem a necessidade de processos manuais.

Para este exemplo, siga as instruções no console para aprender a configurar cada recurso da AWS separadamente, ou siga as instruções do AWS SAM para implantar rapidamente a aplicação usando comandos da AWS CLI.

------
#### [ Console ]

**Para criar a função usando o Console de gerenciamento da AWS**

Primeiro, crie uma função que contenha um código inicial básico. Em seguida, substitua esse código pelo seu próprio código de função ao copiá-lo e colá-lo diretamente no editor de código do Lambda ou ao fazer o upload do código como um pacote `.zip`. Para essa tarefa, recomendamos copiar e colar o código.

1. Abra a [página Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda.

1. Escolha **Create function** (Criar função).

1. Escolha **Author from scratch** (Criar do zero).

1. Em **Basic information** (Informações básicas), faça o seguinte:

   1. Em **Function name** (Nome da função), insira `ScheduledDBMaintenance`.

   1. Em **Runtime**, escolha a versão mais recente do Python.

   1. Em **Architecture** (Arquitetura), escolha **x86\$164**.

1. Escolha a opção **Criar função**.

1. Após a criação da função, você pode configurá-la com o código da função fornecido.

   1. No painel **Origem do código**, substitua o código Hello world criado pelo Lambda com o código da função em Python do arquivo `lambda_function.py` que você salvou anteriormente.

   1. Na seção **DEPLOY**, escolha **Implantar** para atualizar o código da função:  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**Para configurar a memória e o tempo limite da função (console)**

1. Selecione a guia **Configuração** para a função.

1. No painel **Configuração geral**, escolha **Editar**.

1. Defina **Memória** como 256 MB e **Tempo limite** como 15 segundos. Se você estiver processando uma tabela extensa que contém muitos registros, por exemplo, em um ambiente de produção, pode ser útil definir o **Tempo limite** para um número maior. Isso permitirá que sua função tenha mais tempo para realizar a verificação e a limpeza do banco de dados.

1. Escolha **Salvar**.

**Para configurar o formato de log (console)**

É possível configurar as funções do Lambda para gerar logs em formato de texto não estruturado ou em JSON. Recomendamos o uso do formato JSON para logs, pois facilita a busca e a filtragem dos dados de log. Para saber mais sobre as opções de configuração de logs do Lambda, consulte [Configurar controles avançados de registro em log para funções do Lambda](monitoring-logs.md#monitoring-cloudwatchlogs-advanced).

1. Selecione a guia **Configuração** para a função.

1. Na barra lateral, selecione **Ferramentas de monitoramento e operações**.

1. No painel **Configuração de registro em log**, escolha **Editar**.

1. Em **Configuração do registro em log**, selecione **JSON**.

1. Escolha **Salvar**.

**Para configurar as permissões do IAM**

Para conceder à função as permissões necessárias para ler e excluir itens do DynamoDB, você deve adicionar uma política ao [perfil de execução](lambda-intro-execution-role.md) da função, definindo as permissões necessárias.

1. Abra a guia **Configuração** e, em seguida, escolha **Permissões** na barra de navegação esquerda.

1. Escolha o nome do perfil em **Perfil de execução**.

1. No console do IAM, clique em **Adicionar permissões** e, em seguida, em **Criar política em linha**.

1. Use o editor para JSON e insira a seguinte política:  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:Scan",
                   "dynamodb:DeleteItem",
                   "dynamodb:BatchWriteItem"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/MyOrderTable"
           }
       ]
   }
   ```

1. Nomeie a política como **DynamoDBCleanupPolicy** e, em seguida, crie-a.

**Para configurar o Agendador EventBridge como um acionador (console)**

1. Abra o [console do EventBridge](https://console.aws.amazon.com/events/home).

1. No painel de navegação à esquerda, escolha **Agendadores** na seção **Agendador**.

1. Clique em **Criar programação**.

1. Configure o agendamento da seguinte forma:

   1. No campo **Nome do agendamento**, digite um nome para seu agendamento (por exemplo, **DynamoDBCleanupSchedule**).

   1. Em **Padrão de agendamento**, selecione **Agendamento recorrente**.

   1. Em **Tipo de agendamento**, mantenha o padrão como **Agendamento baseado em cron** e, em seguida, insira os seguintes detalhes do agendamento:
      + **Minutos**: **0**
      + **Horas**: **3**
      + **Dia do mês**: **1**
      + **Mês**: **\$1**
      + **Dia da semana**: **?**
      + **Ano**: **\$1**

      Quando avaliada, esta expressão cron é executada no primeiro dia de cada mês às 3h da manhã.

   1. Em **Janela de tempo flexível**, selecione **Desativado**.

1. Escolha **Próximo**.

1. Configure o acionamento para sua função do Lambda da seguinte maneira:

   1. No painel **Detalhes do destino**, mantenha a **API de destino** definida como **Destinos modelados** e, em seguida, selecione **Invocar AWS Lambda**.

   1. Em **Invocar**, selecione a função do Lambda (`ScheduledDBMaintenance`) na lista suspensa.

   1. Mantenha a **Carga útil** vazia e escolha **Próximo**.

   1. Role para baixo até a seção **Permissões** e selecione **Criar um novo perfil para este agendamento**. Ao criar um novo agendamento do Agendador do EventBridge no console, o Agendador do EventBridge gera uma nova política com as permissões exigidas para que o agendamento invoque sua função. Para obter mais informações sobre o gerenciamento de permissões do seu agendamento, consulte [Cron-based schedules](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html#cron-based) no *Guia do usuário do Agendador do EventBridge*.

   1. Escolha **Próximo**.

1. Analise suas configurações e escolha **Criar agendamento** para finalizar a criação do agendamento e do acionador do Lambda.

------
#### [ AWS SAM ]

**Para implantar a aplicação usando o AWS SAM**

1. Acesse a pasta em que você salvou o arquivo `template.yaml` da aplicação. Lembre-se de que este exemplo utiliza dois arquivos `template.yaml`. Verifique se os arquivos estão salvos em subpastas separadas e se você está na pasta correta que contém o modelo para criar a aplicação.

1. Copie os arquivos `lambda_function.py` e `requirements.txt`, que você efetuou o download anteriormente, para a mesma pasta. O local do código especificado no modelo do AWS SAM é `./`, o que significa o diretório atual. O AWS SAM pesquisará nesta pasta o código da função do Lambda quando você tentar implantar a aplicação.

1. Execute o comando a seguir.

   ```
   sam build --use-container
   ```

   Este comando reúne os artefatos de compilação para os recursos que você deseja implantar e os organiza no formato e no local apropriados para a implantação. Especificar a opção `--use-container` compila a função dentro de um contêiner do Docker semelhante ao Lambda. Nós o usamos aqui para que você não precise ter o Python 3.12 instalado na máquina local para que a compilação funcione.

1. Para criar os recursos do Lambda e do Agendador do EventBridge especificados no arquivo `template.yaml`, execute o comando apresentado a seguir.

   ```
   sam deploy --guided
   ```

   Usar o sinalizador `--guided` significa que o AWS SAM mostrará instruções para guiar você no processo de implantação. Para essa implantação, insira **cron-maintenance-app** como `Stack name` e, em seguida, pressione Enter para aceitar os valores padrão para todas as outras opções.

   Quando o AWS SAM concluir a criação dos recursos do Lambda e do Agendador do EventBridge, a mensagem apresentada a seguir deverá ser visualizada.

   ```
   Successfully created/updated stack - cron-maintenance-app in us-west-2
   ```

1. Além disso, é possível confirmar que a função do Lambda foi criada ao abrir a página [Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda. Você deverá visualizar uma função chamada `ScheduledDBMaintenance`.

------

## Testando a aplicação
<a name="scheduled-task-app-test-app"></a>

 Para testar se o agendamento aciona sua função corretamente e se a função limpa os registros do banco de dados conforme o esperado, é possível modificar temporariamente o agendamento para ser executado uma vez em um horário específico. Depois, você pode executar novamente o comando `sam deploy` para redefinir o agendamento recorrente da execução para uma vez por mês. 

**Para executar a aplicação usando o Console de gerenciamento da AWS**

1. Retorne à página do console do Agendador do EventBridge.

1. Escolha seu agendamento e, em seguida, selecione **Editar**.

1. Na seção **Padrão de agendamento**, em **Recorrência**, escolha **Agendamento único**.

1.  Defina o horário de invocação para alguns minutos a partir de agora, analise suas configurações e, em seguida, selecione **Salvar**. 

 Após o agendamento ser executado e invocar o destino, execute o script `test_app.py` para verificar se a função removeu com êxito todos os registros antigos da tabela do DynamoDB. 

**Para verificar se os registros antigos foram excluídos usando um script em Python**

1.  Na linha de comando, navegue até a pasta em que você salvou `test_app.py`. 

1. Executar o script.

   ```
   python test_app.py
   ```

    Se a execução ocorrer com êxito, a saída apresentada a seguir será exibida. 

   ```
   Total number of old records: 0
   ```

## Próximas etapas
<a name="scheduled-task-app-next-steps"></a>

 Agora, você pode modificar o agendamento do Agendador do EventBridge para atender aos requisitos específicos da sua aplicação. O Agendador do EventBridge oferece suporte para as seguintes expressões de agendamento: cron, frequência e agendamentos únicos. 

 Para obter mais informações sobre as expressões de agendamento do Agendador do EventBridge, consulte [Tipos de agendamento](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html) no *Guia do usuário do Agendador do EventBridge*. [Gerenciamento de acesso](https://docs.aws.amazon.com/IAM/latest/UserGuide/access.html) no *Guia do usuário do IAM* 

# Criação de um sistema de processamento de pedidos com funções duráveis do Lambda
<a name="order-processing-app"></a>

**nota**  
NECESSIDADE: adicionar diagrama de arquitetura mostrando o API Gateway, o fluxo de trabalho da função durável e os serviços de suporte (DynamoDB, EventBridge)

## Pré-requisitos
<a name="order-processing-prerequisites"></a>
+ AWS CLI instalado e configurado
+ NECESSIDADE: requisitos específicos de funções duráveis

## Crie os arquivos de código-fonte
<a name="order-processing-source"></a>

Criar os seguintes arquivos em seu diretório do projeto:
+ `lambda_function.py`: o código da função
+ `requirements.txt`: manifesto de dependências

### Código da função
<a name="order-processing-function-code"></a>

```
# NEED: Verify correct imports
import boto3
import json

def lambda_handler(event, context):
    # NEED: Verify DurableContext syntax
    durable = context.durable
    
    try:
        # Validate and store order
        order = await durable.step('validate', async () => {
            return validate_order(event['order'])
        })
        
        # Process payment
        # NEED: Verify wait syntax
        await durable.wait(/* wait configuration */)
        
        # Additional steps
        # NEED: Complete implementation
        
    except Exception as e:
        # NEED: Error handling patterns
        raise e

def validate_order(order_data):
    # NEED: Implementation
    pass
```

### Arquivo de requisitos
<a name="order-processing-requirements"></a>

```
# NEED: List of required packages
```

## Implante o aplicativo
<a name="order-processing-deploy"></a>

### Crie uma tabela do DynamoDB para pedidos
<a name="order-processing-dynamodb"></a>

1. Abra o console do DynamoDB em [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/).

1. Escolha **Create table**

1. Em **Nome da tabela**, insira **Orders**

1. Em **Chave de partição**, insira **orderId**

1. Deixe as outras configurações como o padrão

1. Escolha **Create table**

### Criar a função do Lambda
<a name="order-processing-lambda"></a>

1. Abra o console do Lambda em [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)

1. Escolha **Create function (Criar função)**.

1. Selecione **Criar do zero**

1. Em **Nome da função**, inserir **ProcessOrder**

1. Em **Runtime**, escolha seu runtime preferido

1. NECESSIDADE: adicionar configuração específica de funções duráveis

1. Escolha **Create function (Criar função)**.

### Crie o endpoint do API Gateway
<a name="order-processing-apigateway"></a>

1. Abra o console do API Gateway em [https://console.aws.amazon.com/apigateway/](https://console.aws.amazon.com/apigateway/)

1. Selecione **Criar API**

1. Selecione **API de HTTP**

1. Escolha **Criar**

1. Adicione uma integração com a sua função do Lambda

1. Configure rotas para o processamento de pedidos

1. Implantar a API

## Teste o aplicativo
<a name="order-processing-test"></a>

Envie um pedido de teste:

```
{
    "orderId": "12345",
    "items": [
        {
            "productId": "ABC123",
            "quantity": 1
        }
    ]
}
```

NECESSIDADE: adicionar instruções de monitoramento específicas para funções duráveis

## Próximas etapas
<a name="order-processing-next-steps"></a>

### Adicione a lógica de negócios
<a name="order-processing-business-logic"></a>

Implemente o gerenciamento de inventário:

```
async def check_inventory(order):
    # Add inventory check logic
    pass
```

Adicione os cálculos de preços:

```
async def calculate_total(order):
    # Add pricing logic
    pass
```

### Aprimore o tratamento de erros
<a name="order-processing-error-handling"></a>

Adicione lógica de compensação:

```
async def reverse_payment(order):
    # Add payment reversal logic
    pass
```

Trate os cancelamentos de pedidos:

```
async def cancel_order(order):
    # Add cancellation logic
    pass
```

### Integre os sistemas externos
<a name="order-processing-integrations"></a>

```
async def notify_shipping_provider(order):
    # Add shipping integration
    pass

async def send_customer_notification(order):
    # Add notification logic
    pass
```

### Aprimore o monitoramento
<a name="order-processing-monitoring"></a>
+ Crie painéis do CloudWatch
+ Configure métricas para tempos de processamento de pedidos
+ Configure alertas para pedidos atrasados