

# Cómo empezar con ejemplos de aplicaciones y patrones
<a name="example-apps"></a>

Los siguientes recursos se pueden usar para crear e implementar rápidamente aplicaciones sin servidor que implementen algunos casos de uso comunes de Lambda. Para cada una de las aplicaciones de ejemplo, proporcionamos instrucciones para crear y configurar los recursos manualmente mediante la Consola de administración de AWS IaC o para usar AWS Serverless Application Model para implementar los recursos mediante IaC. Siga las instrucciones de la consola para obtener más información sobre la configuración de los recursos individuales de AWS de cada aplicación o use AWS SAM para implementar rápidamente los recursos como lo haría en un entorno de producción.

## Procesamiento de archivo
<a name="examples-apps-file"></a>
+ **[Aplicación de cifrado de PDF](file-processing-app.md)**: cree una aplicación sin servidor que cifre los archivos PDF cuando se carguen en un bucket de Amazon Simple Storage Service y los guarde en otro bucket, lo que resulta útil para proteger los documentos confidenciales al cargarlos.
+ **[Aplicación de análisis de imágenes](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-example-s3.html)**: cree una aplicación sin servidor que extraiga texto de las imágenes con Amazon Rekognition, lo que resulta útil para el procesamiento de documentos, la moderación de contenido y el análisis automatizado de imágenes.

## Integración de base de datos
<a name="examples-apps-database"></a>
+ **[Aplicación de cola a base de datos](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html)**: cree una aplicación sin servidor que escriba mensajes de cola en una base de datos de Amazon RDS, lo que resulta útil para procesar los registros de los usuarios y gestionar los envíos de pedidos.
+ **[Gestor de eventos de base de datos](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-example-ddb.html)**: cree una aplicación sin servidor que responda a los cambios en las tablas de Amazon DynamoDB, lo que resulta útil para el registro de auditorías, la replicación de datos y los flujos de trabajo automatizados.

## Tareas programadas
<a name="examples-apps-scheduled"></a>
+ **[Aplicación de mantenimiento de base de datos](scheduled-task-app.md)**: cree una aplicación sin servidor que elimine automáticamente las entradas con más de 12 meses de antigüedad de una tabla de Amazon DynamoDB mediante una programación cron, lo que resulta útil para el mantenimiento automatizado de las bases de datos y la administración del ciclo de vida de los datos.
+ **[Creación de una regla programada de EventBridge para funciones de Lambda](https://docs.aws.amazon.com/eventbridge/latest/userguide/run-lambda-schedule.html)**: use expresiones programadas para las reglas en EventBridge para desencadenar una función de Lambda según una programación temporal. Este formato usa la sintaxis cron y se puede configurar con una granularidad de un minuto.

## Flujos de trabajo de larga duración
<a name="examples-apps-workflows"></a>
+ **[Aplicación de procesamiento de pedidos](order-processing-app.md)**: cree una aplicación sin servidor con funciones duraderas que se encargue del procesamiento de pedidos complejos, incluidos el procesamiento de pagos, los controles de inventario y la coordinación de los envíos. En este ejemplo, se muestra cómo crear flujos de trabajo que puedan ejecutarse durante períodos prolongados y, al mismo tiempo, mantener el estado.

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

Utilice los siguientes recursos para explorar más a fondo el desarrollo de aplicaciones Lambda y sin servidor:
+ **[Serverless Land](https://serverlessland.com/)**: una biblioteca de patrones listos para usar para crear aplicaciones sin servidor. Ayuda a los desarrolladores a crear aplicaciones más rápidamente mediante servicios de AWS como Lambda, API Gateway y EventBridge. El sitio ofrece soluciones prediseñadas y prácticas recomendadas, lo que facilita el desarrollo de sistemas sin servidor.
+ **[Aplicaciones de ejemplo de Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-samples.html)**: aplicaciones que están disponibles en el repositorio de GitHub para esta guía. Estos ejemplos muestran el uso de diferentes lenguajes y servicios de AWS. Cada una de las aplicaciones de ejemplo contiene scripts para facilitar la implementación, la limpieza y los recursos de soporte.
+ **[Ejemplos de código para Lambda usando SDK de AWS](https://docs.aws.amazon.com/lambda/latest/dg/service_code_examples.html)**: ejemplos que muestran cómo usar Lambda con kits de desarrollo de software (SDK) de AWS. Estos ejemplos incluyen aspectos básicos, acciones, escenarios y contribuciones de la comunidad de AWS. Los ejemplos abarcan operaciones esenciales, funciones de servicio individuales y tareas específicas que utilizan múltiples funciones o servicios de AWS.

# Creación de una aplicación de procesamiento de archivos sin servidor
<a name="file-processing-app"></a>

Uno de los casos de uso más comunes de Lambda es llevar a cabo tareas de procesamiento de archivos. Por ejemplo, puede utilizar una función de Lambda para crear archivos PDF de forma automática a partir de archivos HTML o imágenes, o para crear miniaturas cuando un usuario carga una imagen.

En este ejemplo, crea una aplicación que cifra los archivos PDF de forma automática cuando se cargan en un bucket de Amazon Simple Storage Service (Amazon S3). Para implementar esta aplicación, necesita crear los siguientes recursos:
+ Un bucket de S3 para que los usuarios puedan cargar los archivos PDF
+ Una función de Lambda en Python que lea el archivo cargado y cree una versión cifrada y protegida por contraseña
+ Un segundo bucket de S3 en el que Lambda pueda guardar el archivo cifrado

También debe crear una política de AWS Identity and Access Management (IAM) para conceder permiso a la función de Lambda para llevar a cabo operaciones de lectura y escritura en los buckets de S3.

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


**sugerencia**  
Si es la primera vez que utiliza Lambda, recomendamos que comience por el tutorial de [Creación de su primera función de Lambda](getting-started.md) antes de crear esta aplicación de ejemplo.

Para implementar la aplicación de forma manual, cree y configure los recursos mediante la Consola de administración de AWS o con la AWS Command Line Interface (AWS CLI). También puede implementar la aplicación mediante AWS Serverless Application Model (AWS SAM). AWS SAM es una herramienta de Infraestructura como código (IaC). Con la IaC no se crean recursos de forma manual, sino que se definen en código y, a continuación, se implementan automáticamente.

Si desea obtener más información sobre el uso de Lambda con la IaC antes de implementar esta aplicación de ejemplo, consulte [Uso de Lambda con la infraestructura como código (IaC)](foundation-iac.md).

## Crear los archivos de código fuente de la función de Lambda
<a name="file-processing-app-download"></a>

Cree los siguientes archivos en el directorio del proyecto:
+ `lambda_function.py`: es el código de la función Python para la función de Lambda que lleva a cabo el cifrado de archivos
+ `requirements.txt`: es un archivo de manifiesto que define las dependencias que requiere el código de la función de Python

Expanda las siguientes secciones para ver el código y obtener más información sobre la función de cada archivo. Para crear los archivos en la máquina local, copie y pegue el siguiente código o descargue los archivos del [repositorio de GitHub aws-lambda-developer-guide](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/file-processing-python).

### Código de la función de Python
<a name="file-processing-app-function-code"></a>

Copie y pegue el siguiente código en un archivo 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**  
En este código de ejemplo, la contraseña del archivo cifrado (`my-secret-password`) está codificada en el código de la función. En aplicaciones de producción, no incluya información confidencial como contraseñas en el código de la función. En su lugar, [cree un secreto de AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) y, a continuación, [utilice la extensión de Lambda AWS Parameters and Secrets](with-secrets-manager.md) para recuperar las credenciales en la función de Lambda.

El código de la función de Python contiene tres funciones: la [función de controlador](python-handler.md) que Lambda ejecuta cuando se invoca la función y dos funciones independientes denominadas `add_encrypted_suffix` y `encrypt_pdf` a las que el controlador llama para que lleve a cabo el cifrado del PDF.

Cuando Amazon S3 invoca la función, Lambda pasa un argumento de *evento* con formato JSON a la función que contiene detalles sobre el evento que provocó la invocación. En este caso, la información incluye el nombre del bucket de S3 y las claves de objeto de los archivos cargados. Para obtener más información sobre el formato del objeto de evento de Amazon S3, consulte [Procese las notificaciones de eventos de Amazon S3 con Lambda.](with-s3.md).

A continuación, la función utiliza AWS SDK para Python (Boto3) para descargar los archivos PDF especificados en el objeto de evento a su directorio de almacenamiento temporal local, antes de cifrarlos mediante la biblioteca [https://pypi.org/project/pypdf/](https://pypi.org/project/pypdf/).

Por último, la función utiliza el SDK de Boto3 para almacenar el archivo cifrado en el bucket de destino de S3.

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

Copie y pegue el siguiente código en un archivo denominado `requirements.txt`.

```
boto3
pypdf
```

En este ejemplo, el código de la función solo tiene dos dependencias que no forman parte de la biblioteca estándar de Python: el SDK para Python (Boto3) y el paquete `pypdf` que la función utiliza para cifrar el PDF.

**nota**  
Como parte del tiempo de ejecución de Lambda, se incluye una versión del SDK para Python (Boto3), de modo que el código se ejecute sin agregar Boto3 al paquete de implementación de la función. Sin embargo, para mantener el control total de las dependencias de la función y evitar posibles problemas de alineación de versiones, la práctica recomendada para Python es incluir todas las dependencias de la función en el paquete de implementación de la función. Consulte [Dependencias de tiempo de ejecución en Python](python-package.md#python-package-dependencies) para obtener más información.

## Implementar la aplicación
<a name="file-processing-app-deploy"></a>

Puede crear e implementar los recursos para esta aplicación de ejemplo de forma manual o mediante AWS SAM. En un entorno de producción, recomendamos que utilice una herramienta de IaC como AWS SAM para implementar aplicaciones sin servidor de forma rápida y repetible sin utilizar procesos manuales.

### Implementación de los recursos de forma manual
<a name="file-processing-app-deploy-manual"></a>

Para implementar la aplicación manualmente:
+ Cree buckets de Amazon S3 de origen y de destino
+ Cree una función de Lambda que cifre un archivo PDF y guarde la versión cifrada de este en un bucket de S3
+ Configure un desencadenador de Lambda que invoque la función cuando se carguen objetos en el bucket de origen

Antes de comenzar, asegúrese de que [Python](https://www.python.org/downloads/) esté instalado en el equipo de compilación.

#### Cree dos buckets de S3
<a name="file-processing-app-deploy-manual-create-buckets"></a>

Primero, cree dos buckets de S3. El primer bucket es el bucket de origen al que subirá los archivos PDF. Lambda utiliza el segundo bucket para guardar el archivo cifrado cuando se invoca la función.

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

**Para crear buckets de S3 (consola)**

1. En la consola de Amazon S3, abra la página [Buckets de uso general](https://console.aws.amazon.com/s3/buckets).

1. Seleccione la Región de AWS más cercana a su ubicación geográfica. Puede cambiar la región por medio de la lista desplegable de la parte superior de la pantalla.  
![\[\]](http://docs.aws.amazon.com/es_es/lambda/latest/dg/images/console_region_select.png)

1. Elija **Crear bucket**.

1. En **Configuración general**, haga lo siguiente:

   1. En **Tipo de bucket**, asegúrese de que **Uso general** está seleccionado.

   1. Para el **Nombre del bucket**, ingrese un nombre único a nivel mundial que cumpla las [reglas de nomenclatura de bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) de Amazon S3. Los nombres de bucket pueden contener únicamente letras minúsculas, números, puntos (.) y guiones (-).

1. Deje el resto de las opciones con sus valores predeterminados y seleccione **Crear bucket**.

1. Repita los pasos 1 a 4 para crear el bucket de destino. En **Nombre del bucket**, introduzca `amzn-s3-demo-bucket-encrypted`, donde `amzn-s3-demo-bucket` es el nombre del bucket de origen que acaba de crear.

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

Antes de comenzar, asegúrese de que la [AWS CLI esté instalada](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) en el equipo de compilación.

**Para crear buckets de Amazon S3 (AWS CLI)**

1. Ejecute el siguiente comando de la CLI para crear el bucket de origen. El nombre que elija para el bucket debe ser globalmente único y seguir las [reglas de nomenclatura de buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) de Amazon S3. Los nombres pueden contener únicamente letras minúsculas, números, puntos (.) y guiones (-). Para `region` y `LocationConstraint`, elija la [Región de AWS](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) más cercana a su ubicación geográfica.

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

   Más adelante en el tutorial, debe crear la función de Lambda en la misma Región de AWS que la del bucket de origen, por lo que debe anotar la región que eligió.

1. Ejecute el siguiente comando para crear el bucket de destino. Para el nombre del bucket, debe utilizar `amzn-s3-demo-bucket-encrypted`, donde `amzn-s3-demo-bucket` es el nombre del bucket de origen que creó en el paso 1. Para `region` y `LocationConstraint`, elija la misma Región de AWS que usó para crear el bucket de origen.

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

------

#### Creación de un rol de ejecución
<a name="file-processing-app-deploy-manual-create-execution-role"></a>

Un rol de ejecución es un rol de IAM que concede a la función de Lambda permiso para acceder a servicios y recursos de Servicios de AWS. Para conceder acceso de lectura y escritura a Amazon S3 a la función, debe adjuntar la [política administrada de AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) `AmazonS3FullAccess`.

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

**Para crear un rol de ejecución y adjuntar la política administrada `AmazonS3FullAccess` (consola)**

1. Abra la [página Roles](https://console.aws.amazon.com/iam/home/roles) en la consola de IAM.

1. Elija **Crear rol**.

1. En **Tipo de entidad de confianza**, seleccione **Servicio de AWS** y, en **Caso de uso**, seleccione **Lambda**.

1. Elija **Siguiente**.

1. Agregue la política administrada `AmazonS3FullAccess` de la siguiente manera:

   1. En **Políticas de permisos**, ingrese **AmazonS3FullAccess** en la barra de búsqueda.

   1. Seleccione la casilla situada junto a la política administrada.

   1. Elija **Siguiente**.

1. En **Detalles del rol**, para **Nombre de rol**, escriba **LambdaS3Role**.

1. Seleccione **Creación de rol**.

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

**Crear un rol de ejecución y adjuntar la política administrada `AmazonS3FullAccess` (AWS CLI)**

1. Guarde el siguiente JSON en un archivo llamado `trust-policy.json`. Esta política de confianza permite a Lambda utilizar los permisos del rol al dar permiso al servicio principal `lambda.amazonaws.com` para llamar a la acción de AWS Security Token Service (AWS STS) `AssumeRole`.  
****  

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

1. Desde el directorio en el que guardó el documento de política de confianza JSON, ejecute el siguiente comando de la CLI para crear el rol de ejecución.

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

1. Para adjuntar la política administrada `AmazonS3FullAccess`, ejecute el siguiente comando de la CLI:

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

------

#### Crear el paquete de despliegue de la función
<a name="file-processing-app-deploy-manual-create-function-package"></a>

Para crear una función, debe crear un *paquete de despliegue* que contenga el código y las dependencias de la función. Para esta aplicación, el código de la función utiliza una biblioteca independiente para el cifrado de PDF.

**Creación del paquete de implementación**

1. Navegue hasta el directorio del proyecto que contiene los archivos `lambda_function.py` y `requirements.txt` que creó o descargó de GitHub anteriormente y cree un nuevo directorio denominado `package`.

1. Instale las dependencias especificadas en el archivo `requirements.txt` del directorio `package` ejecutando el siguiente comando:

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

1. Cree un archivo .zip que contenga el código de la aplicación y todas sus dependencias. En Linux o macOS, ejecute los siguientes comandos desde la interfaz de la línea de comandos.

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

    En Windows, utilice la herramienta de compresión que prefiera para crear el archivo `lambda_function.zip`. Asegúrese de que el archivo `lambda_function.py` y las carpetas que contienen las dependencias estén en la raíz del archivo .zip.

También puede crear su paquete de implementación mediante un entorno virtual de Python. Consulte [Uso de archivos .zip para funciones de Lambda en Python](python-package.md)

#### Crear la función de Lambda
<a name="file-processing-app-deploy-manual-createfunction"></a>

Ahora use el paquete de implementación que creó en el paso anterior para implementar la función de Lambda.

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

**Para crear la función (consola)**

Para crear una función de Lambda con la consola, primero debe crear una función básica que contenga el código “Hola, mundo”. A continuación, reemplace este código por su propio código de función mediante la carga del archivo .zip que creó en el paso anterior.

Para garantizar que no se agote el tiempo de espera de la función cuando cifra archivos PDF de gran tamaño, debe configurar los ajustes de memoria y tiempo de espera de la función. El formato de registro de la función también se establece como JSON. Es necesario configurar los registros con formato JSON cuando se utiliza el script de prueba proporcionado para que pueda leer el estado de invocación de la función desde los registros de CloudWatch y confirmar que la invocación se llevó a cabo de forma correcta.

1. Abra la página de [Funciones](https://console.aws.amazon.com/lambda/home#/functions) en la consola de Lambda.

1. Asegúrese de trabajar en la misma Región de AWS en la que creó el bucket de S3. Puede cambiar la región por medio de la lista desplegable de la parte superior de la pantalla.  
![\[\]](http://docs.aws.amazon.com/es_es/lambda/latest/dg/images/console_region_select.png)

1. Elija **Crear función**.

1. Elija **Crear desde cero**.

1. Bajo **Información básica**, haga lo siguiente:

   1. En **Nombre de la función**, introduzca `EncryptPDF`.

   1. En **Tiempo de ejecución**, seleccione **Python 3.12**.

   1. En **Arquitectura**, elija **x86\$164**.

1. Adjunte el rol de ejecución que creó en el paso anterior de la siguiente manera:

   1. Expanda la sección **Cambiar el rol de ejecución predeterminado**.

   1. Seleccione **Usar un rol existente**.

   1. En **Rol existente**, seleccione su rol (`LambdaS3Role`).

1. Seleccione **Creación de función**.

**Para cargar el código de la función (consola)**

1. En el panel **Código fuente**, elija **Cargar desde**.

1. Elija un **archivo .zip**.

1. Seleccione **Cargar**.

1. En el selector de archivos, seleccione un archivo .zip y luego elija **Abrir**.

1. Seleccione **Save**.

**Configuración de la memoria y el tiempo de espera de la función (consola)**

1. Seleccione la pestaña **Configuración** de la función.

1. En el panel **Configuración general**, seleccione **Editar**.

1. Establezca la **Memoria** en 256 MB y el **Tiempo de espera** en 15 segundos.

1. Seleccione **Save**.

**Configuración del formato de registro (consola)**

1. Seleccione la pestaña **Configuración** de la función.

1. Seleccione **Herramientas de supervisión y operaciones**.

1. En el panel **Configuración de registros**, seleccione **Editar**.

1. Para la **configuración de registro**, seleccione **JSON**.

1. Seleccione **Save**.

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

**Para crear la función (AWS CLI)**
+ Ejecute el siguiente comando desde el directorio que contiene el archivo `lambda_function.zip`. Para el parámetro `region`, reemplace `us-east-2` por la región en la que creó los buckets de 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
  ```

------

#### Configuración de un desencadenador de Amazon S3 para invocar una función
<a name="file-processing-app-deploy-manual-configure-s3-trigger"></a>

Para que la función de Lambda se ejecute cuando carga un archivo al bucket de origen, debe configurar un desencadenador para la función. Puede configurar el desencadenador de Amazon S3 mediante la consola o la AWS CLI.

**importante**  
Este procedimiento configura el bucket de S3 para invocar su función cada vez que se crea un objeto en el bucket. Asegúrese de configurar esto solo en el bucket de origen. Si la función de Lambda crea objetos en el mismo bucket que la invoca, la función se puede [invocar de forma continua en un bucle](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway). Esto puede provocar que se facturen cargos imprevistos en su Cuenta de AWS.

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

**Para configurar el desencadenador de Amazon S3 (consola)**

1. Abra la [página Funciones](https://console.aws.amazon.com/lambda/home#/functions) de la consola de Lambda y elija la función (`EncryptPDF`).

1. Elija **Add trigger (Añadir disparador)**.

1. Seleccione **S3**.

1. En **Bucket**, seleccione el bucket de origen.

1. En **Tipos de eventos**, seleccione **Todos los eventos de creación de objetos**.

1. En **Recursive invocation** (Invocación recursiva), marque la casilla de verificación para confirmar que no se recomienda utilizar el mismo bucket de S3 para la entrada y la salida. Puede obtener más información sobre los patrones de invocación recursiva en Lambda en [Patrones recursivos que provocan funciones de Lambda descontroladas](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway) en Serverless Land.

1. Elija **Agregar**.

   Al crear un desencadenador mediante la consola de Lambda, Lambda crea automáticamente una [política basada en recursos](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) para conceder permiso al servicio que seleccione para invocar la función. 

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

**Para configurar el desencadenador de Amazon S3 (AWS CLI)**

1. Agregue una [política basada en recursos](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) a la función que permita que el bucket de origen de Amazon S3 invoque la función al agregar un archivo. Una instrucción de política basada en recursos concede permisos a otros Servicios de AWS para invocar la función. Para conceder permisos a Amazon S3 para invocar la función, ejecute el siguiente comando de la CLI. Asegúrese de reemplazar el parámetro `source-account` por su propio ID de Cuenta de AWS y de utilizar su propio nombre de bucket de origen.

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

   La política que defina con este comando permite a Amazon S3 invocar la función solo cuando se lleva a cabo una acción en el bucket de origen.
**nota**  
Si bien los nombres de los buckets de S3 son únicos a nivel mundial, cuando se utilizan políticas basadas en recursos, se recomienda aclarar que el bucket debe pertenecer a la cuenta. Esto sucede porque si elimina un bucket, es posible que otra Cuenta de AWS cree un bucket con el mismo Nombre de recurso de Amazon (ARN).

1. Guarde el siguiente JSON en un archivo llamado `notification.json`. Cuando se aplica al bucket de origen, este JSON configura el bucket para enviar una notificación a la función de Lambda cada vez que se agrega un objeto nuevo. Reemplace el número de Cuenta de AWS y la Región de AWS en el ARN de la función de Lambda por su número de cuenta y su región.

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

1. Ejecute el siguiente comando de la CLI para aplicar la configuración de notificación del archivo JSON que creó al bucket de origen. Reemplace `amzn-s3-demo-bucket` por el nombre del bucket de origen.

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

   Para obtener más información sobre el comando `put-bucket-notification-configuration` y la opción `notification-configuration`, consulte [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html) en la *Referencia de comandos de la CLI AWS*.

------

### Implementación de los recursos mediante AWS SAM
<a name="file-processing-app-deploy-sam"></a>

Antes de empezar, asegúrese de que [Docker](https://docs.docker.com/get-docker/) y [la última versión de AWS SAMCLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) estén instalados en su máquina de compilación.

1. En el directorio del proyecto, copie y pegue el siguiente código en un nuevo archivo denominado `template.yaml`. Sustituya los nombres de los buckets del marcador de posición:
   + Para el bucket de origen, sustituya `amzn-s3-demo-bucket` por cualquier nombre que cumpla con las [reglas de nomenclatura del bucket de S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html).
   + Para el bucket de destino, reemplace `amzn-s3-demo-bucket-encrypted` por `<source-bucket-name>-encrypted` cuando `<source-bucket>` sea el nombre que escogió para el bucket de origen.

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

   La plantilla AWS SAM define los recursos que crea para la aplicación. En este ejemplo, la plantilla define una función de Lambda con el tipo `AWS::Serverless::Function` y dos buckets de S3 con el tipo `AWS::S3::Bucket`. Los nombres de los buckets especificados en la plantilla son marcadores de posición. Antes de implementar la aplicación mediante AWS SAM, debe editar la plantilla para cambiar el nombre de los buckets por nombres únicos a nivel mundial que cumplan con las [reglas de nomenclatura para los buckets de S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html). Este paso se explica con más detalle en [Implementación de los recursos mediante AWS SAM](#file-processing-app-deploy-sam).

   La definición del recurso de la función de Lambda configura un desencadenador para la función mediante la propiedad del evento `S3Event`. Este desencadenador hace que se invoque la función cada vez que se crea un objeto en el bucket de origen.

   La definición de la función también especifica una política de AWS Identity and Access Management (IAM) que se adjuntará al [rol de ejecución](lambda-intro-execution-role.md) de la función. La [política administrada de AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) `AmazonS3FullAccess` proporciona a su función los permisos que necesita para leer y escribir objetos en Amazon S3.

1. Ejecute el comando a continuación en el directorio en el que guardó los archivos `template.yaml`, `lambda_function.py` y `requirements.txt`.

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

   Este comando recopila los artefactos de compilación de la aplicación y los coloca en el formato y la ubicación adecuados para implementarlos. Con la opción `--use-container`, la función se crea dentro de un contenedor de Docker tipo Lambda. Lo usamos aquí para que no necesite tener Python 3.12 instalado en su máquina local para que la compilación funcione.

   Durante el proceso de compilación, AWS SAM busca el código de la función de Lambda en la ubicación que especificó con la propiedad `CodeUri` en la plantilla. En este caso, especificamos el directorio actual como la ubicación (`./`).

   Si hay un archivo `requirements.txt`, AWS SAM lo usa para recopilar las dependencias especificadas. De forma predeterminada, AWS SAM crea un paquete de implementación .zip con el código y las dependencias de la función. También puede optar por implementar la función como una imagen de contenedor mediante la propiedad [PackageType](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-packagetype).

1. Para implementar la aplicación y crear los recursos de Lambda y Amazon S3 especificados en la plantilla de AWS SAM, ejecute el siguiente comando:

   ```
   sam deploy --guided
   ```

   El uso de la marca `--guided` significa que AWS SAM le mostrará instrucciones para guiarlo a lo largo del proceso de implementación. Para esta implementación, acepte las opciones predeterminadas pulsando Intro.

Durante el proceso de implementación, AWS SAM crea los siguientes recursos en su Cuenta de AWS:
+ Una [pila](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html#cfn-concepts-stacks) de CloudFormation llamada `sam-app`
+ Una función de Lambda con el nombre `EncryptPDF`
+ Dos buckets de S3 con los nombres que eligió cuando editó el archivo de plantilla `template.yaml` de AWS SAM
+ Un rol de ejecución de IAM para la función con el formato de nombre `sam-app-EncryptPDFFunctionRole-2qGaapHFWOQ8`

Cuando AWS SAM termine de crear los recursos, debería ver el siguiente mensaje:

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

## Probar la aplicación
<a name="file-processing-app-test"></a>

Para probar la aplicación, cargue un archivo PDF en el bucket de origen y confirme que Lambda crea una versión cifrada del archivo en el bucket de destino. En este ejemplo, puede probarlo de forma manual mediante la consola o la AWS CLI o usando el script de prueba proporcionado.

Para las aplicaciones de producción, puede utilizar métodos y técnicas de prueba tradicionales, como las pruebas unitarias, para confirmar el correcto funcionamiento del código de la función de Lambda. La mejor práctica también es implementar pruebas como las del script de prueba proporcionado, que llevan a cabo pruebas de integración con recursos reales basados en la nube. Las pruebas de integración en la nube confirman que la infraestructura se desplegó correctamente y que los eventos fluyen entre los distintos servicios según lo esperado. Para obtener más información, consulte [Cómo realizar pruebas de funciones y aplicaciones sin servidor](testing-guide.md).

### Prueba de la aplicación de forma manual
<a name="file-processing-app-test-manual"></a>

Para probar la función de forma manual, agregue un archivo PDF a su bucket de origen de Amazon S3. Cuando agrega el archivo al bucket de origen, la función de Lambda se debe invocar de forma automática y debe almacenar una versión cifrada del archivo en el bucket de destino.

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

**Prueba de la aplicación cargando un archivo (consola)**

1. Para cargar un archivo PDF en el bucket de S3, haga lo siguiente:

   1. Abra la página [Buckets](https://console.aws.amazon.com/s3/buckets) de la consola de Amazon S3 y elija el bucket de origen.

   1. Seleccione **Cargar**.

   1. Elija **Agregar archivos** y utilice el selector de archivos para elegir el archivo PDF que desea cargar.

   1. Elija **Abrir** y, a continuación, **Cargar**.

1. Compruebe que Lambda haya guardado una versión cifrada del archivo PDF en el bucket de destino, de la siguiente manera:

   1. Vuelva a la página [Buckets](https://console.aws.amazon.com/s3/buckets) de la consola de Amazon S3 y elija el bucket de destino.

   1. En el panel **Objetos**, ahora debería ver un archivo con el formato de nombre `filename_encrypted.pdf` (en el que `filename.pdf` es el nombre del archivo que cargó en el bucket de origen). Para descargar el PDF cifrado, seleccione el archivo y luego elija **Descargar**.

   1. Confirme que puede abrir el archivo descargado con la contraseña con la que lo protegió la función de Lambda (`my-secret-password`).

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

**Prueba de la aplicación cargando un archivo (AWS CLI)**

1. Desde el directorio que contiene el archivo PDF que desea cargar, ejecute el siguiente comando de la CLI: Reemplace el parámetro `--bucket` con el nombre del bucket de origen. Para los parámetros `--key` y `--body`, utilice el nombre de archivo del archivo de prueba.

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

1. Compruebe que la función creó una versión cifrada del archivo y la guardó en el bucket de S3 de destino. Ejecute el siguiente comando de la CLI, para ello reemplace `amzn-s3-demo-bucket-encrypted` por el nombre del bucket de destino.

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

   Si la función se ejecuta correctamente, verá un resultado similar al siguiente. El bucket de destino debe contener un archivo con el formato de nombre `<your_test_file>_encrypted.pdf`, en el que `<your_test_file>` es el nombre del archivo cargado.

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

1. Para descargar el archivo que Lambda guardó en el bucket de destino, ejecute el siguiente comando de la CLI: Reemplace el parámetro `--bucket` con el nombre del bucket de destino. Para el parámetro `--key`, utilice el nombre de archivo `<your_test_file>_encrypted.pdf`, en el que `<your_test_file>` es el nombre del archivo de prueba que cargó.

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

   Este comando descarga el archivo en el directorio actual y lo guarda como `my_encrypted_file.pdf`.

1. Confirme que puede abrir el archivo descargado con la contraseña con la que lo protegió la función de Lambda (`my-secret-password`).

------

### Prueba de la aplicación con el script automatizado
<a name="file-processing-app-test-auto"></a>

Cree los siguientes archivos en el directorio del proyecto:
+ `test_pdf_encrypt.py`: es un script de prueba que puede usar para probar la aplicación de forma automática
+ `pytest.ini`: es un archivo de configuración para el script de prueba

Expanda las siguientes secciones para ver el código y obtener más información sobre la función de cada archivo.

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

Copie y pegue el siguiente código en un archivo denominado `test_pdf_encrypt.py`. Asegúrese de reemplazar los nombres de los buckets del marcador de posición:
+ En la función `test_source_bucket_available`, reemplace `amzn-s3-demo-bucket` por el nombre de su bucket de origen.
+ En la función `test_encrypted_file_in_bucket`, reemplace `amzn-s3-demo-bucket-encrypted` por `source-bucket-encrypted`, cuando `source-bucket>` sea el nombre del bucket de origen.
+ En la función `cleanup`, sustituya `amzn-s3-demo-bucket` por el nombre del bucket de origen y reemplace `amzn-s3-demo-bucket-encrypted` por el nombre del 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
```

El script de prueba automatizado ejecuta tres funciones de prueba para confirmar el correcto funcionamiento de la aplicación:
+ La prueba `test_source_bucket_available` confirma que el bucket de origen se creó correctamente mediante la carga de un archivo PDF de prueba en el bucket.
+ La prueba `test_lambda_invoked` consulta el último flujo de registro de los registros de CloudWatch de la función para confirmar que la función de Lambda se ejecutó correctamente cuando cargó el archivo de prueba.
+ La prueba `test_encrypted_file_in_bucket` confirma que el bucket de destino contiene el archivo cifrado `test_encrypted.pdf`.

Una vez ejecutadas todas estas pruebas, el script ejecuta un paso de limpieza adicional para eliminar los archivos `test.pdf` y `test_encrypted.pdf` de los buckets de origen y destino.

Los nombres de los buckets especificados en este archivo son marcadores de posición, al igual que en la plantilla AWS SAM. Antes de ejecutar la prueba, debe editar este archivo con los nombres reales de los buckets de la aplicación. Este paso se explica con más detalle en [Prueba de la aplicación con el script automatizado](#file-processing-app-test-auto)

#### Prueba del archivo de configuración del script
<a name="file-processing-app-test-config"></a>

Copie y pegue el siguiente código en un archivo denominado `pytest.ini`.

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

Esto es necesario para especificar el orden en el que se ejecutan las pruebas del script `test_pdf_encrypt.py`.

Para ejecutar las pruebas, haga lo siguiente:

1. Asegúrese de que el módulo `pytest` esté instalado en el entorno local. Puede instalar `pytest` ejecutando el siguiente comando:

   ```
   pip install pytest
   ```

1. Guarde un archivo PDF con el nombre `test.pdf` en el directorio que contiene los archivos `test_pdf_encrypt.py` y `pytest.ini`.

1. Abra un programa de terminal o intérprete de comandos y ejecute el siguiente comando desde el directorio que contiene los archivos de prueba:

   ```
   pytest -s -v
   ```

   Cuando concluya la prueba, la salida debe tener el siguiente aspecto:

   ```
   ============================================================== 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 ==========================================================
   ```

## Siguientes pasos
<a name="file-processing-app-next-steps"></a>

Ahora que creó esta aplicación de ejemplo, puede usar el código proporcionado como base para crear otros tipos de aplicaciones de procesamiento de archivos. Modifique el código del archivo `lambda_function.py` para implementar la lógica de procesamiento de archivos para su caso de uso.

Muchos casos de uso típicos del procesamiento de archivos implican el procesamiento de imágenes. Cuando se usa Python, las bibliotecas de procesamiento de imágenes más populares, como [pillow](https://pypi.org/project/pillow/), suelen contener componentes de C o C\$1\$1. Para garantizar que el paquete de implementación de la función sea compatible con el entorno de ejecución de Lambda, es importante utilizar la distribución binaria de origen correcta.

Cuando implemente los recursos con AWS SAM, debe tomar algunas medidas adicionales para incluir la distribución de origen correcta en el paquete de implementación. Como AWS SAM no instalará dependencias para una plataforma diferente a la de la máquina de compilación, especificar la distribución de origen (archivo `.whl`) correcta en su archivo `requirements.txt` no funcionará si la máquina de compilación usa un sistema operativo o una arquitectura diferente del entorno de ejecución de Lambda. En su lugar, lleve a cabo una de las siguientes acciones:
+ Use la opción `--use-container` cuando ejecute `sam build`. Cuando especifica esta opción, AWS SAM descarga una imagen base de contenedor compatible con el entorno de ejecución de Lambda y compila el paquete de implementación de la función en un contenedor de Docker con esa imagen. Para obtener más información, consulte [Creación de una función de Lambda dentro de un contenedor proporcionado](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-build.html#using-sam-cli-build-options-container).
+ Cree usted mismo el paquete de implementación .zip de la función con la distribución binaria de origen correcta y guarde el archivo .zip en el directorio que especifique como `CodeUri` en la plantilla AWS SAM. Para obtener más información sobre la compilación de paquetes de implementación .zip para Python mediante distribuciones binarias, consulte [Creación de un paquete de despliegue .zip con dependencias](python-package.md#python-package-create-dependencies) y [Creación de paquetes de despliegue .zip con bibliotecas nativas](python-package.md#python-package-native-libraries).

# Creación de una aplicación para llevar a cabo el mantenimiento programado de la base de datos
<a name="scheduled-task-app"></a>

Puede utilizar AWS Lambda para reemplazar los procesos programados, como las copias de seguridad automatizadas del sistema, las conversiones de archivos y las tareas de mantenimiento. En este ejemplo, se crea una aplicación sin servidor que lleva a cabo un mantenimiento programado regular en una tabla de DynamoDB mediante la eliminación de entradas antiguas. La aplicación utiliza el Programador de EventBridge para invocar una función de Lambda según una programación cron. Cuando se invoca, la función consulta la tabla en busca de elementos con más de un año de antigüedad y los elimina. La función registra cada elemento eliminado en Registros de CloudWatch.

Para implementar este ejemplo, cree antes una tabla de DynamoDB y llénela con algunos datos de prueba para que la función los consulte. A continuación, cree una función de Lambda de Python con un desencadenador del Programador de EventBridge y un rol de ejecución de IAM que dé permiso a la función para leer y eliminar elementos de la tabla.

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


**sugerencia**  
Si es la primera vez que utiliza Lambda, recomendamos que complete el tutorial [Creación de su primera función de Lambda](getting-started.md) antes de crear esta aplicación de ejemplo.

Para implementar la aplicación manualmente, cree y configure los recursos con la Consola de administración de AWS. También puede implementar la aplicación mediante AWS Serverless Application Model (AWS SAM). AWS SAM es una herramienta de Infraestructura como código (IaC). Con la IaC no se crean recursos de forma manual, sino que se definen en código y, a continuación, se implementan automáticamente.

Si desea obtener más información sobre el uso de Lambda con la IaC antes de implementar esta aplicación de ejemplo, consulte [Uso de Lambda con la infraestructura como código (IaC)](foundation-iac.md).

## Requisitos previos
<a name="scheduled-task-app-prereqs"></a>

Antes de poder crear la aplicación de ejemplo, asegúrese de tener instaladas los programas y las herramientas de línea de comando necesarios.
+ **Python**

  Para rellenar la tabla de DynamoDB que ha creado para probar la aplicación, en este ejemplo se utiliza un script de Python y un archivo CSV para escribir datos en la tabla. Asegúrese de tener instalado en el equipo la versión 3.8 o posterior de Python.
+ **AWS SAM CLI**

  Si desea crear la tabla de DynamoDB e implementar la aplicación de ejemplo mediante AWS SAM, debe instalar la AWS SAM CLI. Siga las [instrucciones de instalación](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) en la *Guía del usuario de AWS SAM*.
+ **AWS CLI**

  Para utilizar el script de Python proporcionado para rellenar la tabla de prueba, debe tener instalada y configurada la AWS CLI. Esto se debe a que el script usa AWS SDK para Python (Boto3), que necesita acceder a sus credenciales de AWS Identity and Access Management (IAM). También necesita la AWS CLI instalada para implementar los recursos mediante AWS SAM. Para instalar la CLI, siga las [instrucciones de instalación](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) en la *Guía del usuario de AWS Command Line Interface*.
+ **Docker**

  Para implementar la aplicación con AWS SAM, Docker también debe estar instalado en la máquina de compilación. Siga las instrucciones de [Instalar Docker Engine](https://docs.docker.com/engine/install/) en el sitio web de documentación de Docker.

## Descarga de los archivos de la aplicación de ejemplo
<a name="scheduled-task-app-download"></a>

Para crear la base de datos de ejemplo y la aplicación con el mantenimiento programado, debe crear los siguientes archivos en el directorio del proyecto:

**Ejemplos de archivos de base de datos**
+ `template.yaml`: una plantilla de AWS SAM que puede utilizar para crear la tabla de DynamoDB
+ `sample_data.csv`: un archivo CSV que contiene datos de muestra para cargarlos en la tabla
+ `load_sample_data.py`: un script de Python que escribe los datos del archivo CSV en la tabla

**Archivos de la aplicación con el mantenimiento programado**
+ `lambda_function.py`: es el código de la función de Python para la función de Lambda que lleva a cabo el mantenimiento de la base de datos
+ `requirements.txt`: es un archivo de manifiesto que define las dependencias que requiere el código de la función de Python
+ `template.yaml`: es una plantilla de AWS SAM que puede usar para implementar la aplicación

**Archivo de prueba**
+ `test_app.py`: un script de Python que analiza la tabla y confirma el correcto funcionamiento de la función al generar todos los registros con más de un año de antigüedad

Expanda las siguientes secciones para ver el código y obtener más información sobre la función de cada archivo a la hora de crear y probar la aplicación. Para crear los archivos en su equipo local, copie y pegue el siguiente código.

### Plantilla de AWS SAM (ejemplo de tabla de DynamoDB)
<a name="scheduled-task-app-table-yaml"></a>

Copie y pegue el siguiente código en un archivo 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**  
Las plantillas de AWS SAM utilizan una convención de nomenclatura estándar de `template.yaml`. En este ejemplo, tiene dos archivos de plantilla: uno para crear la base de datos del ejemplo y otro para crear la propia aplicación. Guárdelos en subdirectorios separados de la carpeta del proyecto.

Esta plantilla de AWS SAM define el recurso de la tabla de DynamoDB que se crea para probar la aplicación. La tabla usa una clave principal de `Order_number` con una clave de clasificación de `Date`. Para que la función de Lambda busque los elementos directamente por fecha, también definimos un [Índice secundario global](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html) denominado `Date-index`.

Para obtener más información sobre cómo crear y configurar una tabla de DynamoDB con el recurso `AWS::DynamoDB::Table`, consulte [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html) en la *Guía del usuario de AWS CloudFormation*.

### Archivo de datos de base de datos de ejemplo
<a name="scheduled-task-app-csv-file"></a>

Copie y pegue el siguiente código en un archivo 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 archivo contiene algunos datos de prueba de ejemplo con los que rellenar la tabla de DynamoDB en un formato de valores separados por comas (CSV) estándar.

### Script de Python para cargar datos de muestra
<a name="scheduled-task-app-load-script"></a>

Copie y pegue el siguiente código en un archivo 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.")
```

Este script de Python utiliza primero AWS SDK para Python (Boto3) para crear una conexión con la tabla de DynamoDB. A continuación, recorre en iteración cada fila del archivo CSV de datos de ejemplo, crea un elemento a partir de esa fila y escribe el elemento en la tabla de DynamoDB mediante el SDK de Boto3.

### Código de la función de Python
<a name="scheduled-task-app-function-code"></a>

Copie y pegue el siguiente código en un archivo 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'
    }
```

El código de la función de Python contiene la [función de controlador](python-handler.md) (`lambda_handler`) que Lambda ejecuta cuando se invoca la función.

Cuando el Programador de EventBridge invoca la función, utiliza AWS SDK para Python (Boto3) para crear una conexión con la tabla de DynamoDB en la que se va a llevar a cabo la tarea de mantenimiento programada. A continuación, utiliza la biblioteca `datetime` de Python para calcular la fecha de hace un año, antes de analizar la tabla en busca de elementos anteriores a este y eliminarlos.

Tenga en cuenta que las respuestas de las operaciones de consulta y análisis de DynamoDB están limitadas a un tamaño máximo de 1 MB. Si la respuesta es superior a 1 MB, DynamoDB pagina los datos y devuelve un elemento `LastEvaluatedKey` de la respuesta. Para garantizar que nuestra función procese todos los registros de la tabla, comprobamos la presencia de esta clave y continuamos analizando la tabla desde la última posición evaluada hasta analizar toda la tabla.

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

Copie y pegue el siguiente código en un archivo denominado `requirements.txt`.

```
boto3
```

En este ejemplo, el código de la función solo tiene una dependencia que no forma parte de la biblioteca estándar de Python: el SDK para Python (Boto3) que la función utiliza para analizar y eliminar elementos de la tabla de DynamoDB.

**nota**  
Como parte del tiempo de ejecución de Lambda, se incluye una versión del SDK para Python (Boto3), de modo que el código se ejecute sin agregar Boto3 al paquete de implementación de la función. Sin embargo, para mantener el control total de las dependencias de la función y evitar posibles problemas de alineación de versiones, la práctica recomendada para Python es incluir todas las dependencias de la función en el paquete de implementación de la función. Consulte [Dependencias de tiempo de ejecución en Python](python-package.md#python-package-dependencies) para obtener más información.

### Plantilla de AWS SAM (aplicación con el mantenimiento programado)
<a name="scheduled-task-app-table-yaml"></a>

Copie y pegue el siguiente código en un archivo 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**  
Las plantillas de AWS SAM utilizan una convención de nomenclatura estándar de `template.yaml`. En este ejemplo, tiene dos archivos de plantilla: uno para crear la base de datos del ejemplo y otro para crear la propia aplicación. Guárdelos en subdirectorios separados de la carpeta del proyecto.

Esta plantilla de AWS SAM define los recursos de la aplicación. Definimos la función de Lambda con el recurso `AWS::Serverless::Function`. La programación del Programador de EventBridge y el desencadenador para invocar la función de Lambda se crean mediante la propiedad `Events` de este recurso mediante un tipo de `ScheduleV2`. Para obtener más información sobre cómo definir programaciones del Programador de EventBridge en plantillas de AWS SAM, consulte [ScheduleV2](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-schedulev2.html) en la *Guía para desarrolladores de AWS Serverless Application Model*.

Además de la función de Lambda y la programación del Programador de EventBridge, también definimos un grupo de registros de CloudWatch para que la función envíe los registros de los elementos eliminados.

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

Copie y pegue el siguiente código en un archivo 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 prueba utiliza AWS SDK para Python (Boto3) para crear una conexión con la tabla de DynamoDB y buscar elementos con más de un año de antigüedad. Para confirmar si la función de Lambda se ha ejecutado correctamente, al final de la prueba, la función imprime el número de registros con más de un año de antigüedad que aún se encuentran en la tabla. Si la función de Lambda se ejecutó correctamente, el número de registros antiguos de la tabla debería ser cero. 

## Creación y llenado de la tabla de DynamoDB de ejemplo
<a name="scheduled-task-app-create-table"></a>

Para probar la aplicación con el mantenimiento programado, antes debe crear una tabla de DynamoDB y rellenarla con algunos datos de ejemplo. Puede crear la tabla manualmente mediante la Consola de administración de AWS o AWS SAM. Le recomendamos que utilice AWS SAM para crear y configurar rápidamente la tabla mediante unos pocos comandos de la AWS CLI.

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

**Creación de la tabla de DynamoDB**

1. Abra la [página Tables (Tablas) en la consola de DynamoDB](https://console.aws.amazon.com/dynamodbv2/home#tables).

1. Seleccione **Create table (Creación de tabla)**.

1. Haga lo siguiente para crear la tabla:

   1. En **Detalles de la tabla**, en **Nombre de la tabla**, ingrese **MyOrderTable**.

   1. En **Clave de partición**, ingrese **Order\$1number** y mantenga el tipo de datos establecido como **Cadena**.

   1. En **Clave de clasificación**, ingrese **Date** y mantenga el tipo de datos establecido como **Cadena**.

   1. Deje la **Configuración de la tabla** establecida en **Configuración predeterminada** y elija **Crear tabla**.

1. Cuando la tabla haya terminado de crearse y su **Estado** aparezca como **Activo**, cree un índice secundario global (GSI) de la siguiente manera. La aplicación utilizará este GSI para buscar elementos directamente por fecha y determinar qué elementos se van a eliminar.

   1. Elija **MyOrderTable** en la lista de tablas.

   1. Seleccione la pestaña **Índices**.

   1. En **Índices secundarios globales**, elija **Crear índice**.

   1. En **Detalles del índice**, ingrese **Date** en **Clave de partición** y deje el **Tipo de datos** establecido en **Cadena**.

   1. En **Nombre de índice**, ingrese el **Date-index**.

   1. Deje los demás parámetros con los valores predeterminados, desplácese a la parte inferior de la página y elija **Crear índice**.

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

**Creación de la tabla de DynamoDB**

1. Vaya a la carpeta en la que guardó el archivo `template.yaml` de la tabla de DynamoDB. Tenga en cuenta que en este ejemplo se utilizan dos archivos `template.yaml`. Asegúrese de que estén guardados en subcarpetas independientes y de que se encuentra en la carpeta correcta que contiene la plantilla para crear la tabla de DynamoDB.

1. Ejecute el siguiente comando.

   ```
   sam build
   ```

   Este comando recopila los artefactos de compilación de los recursos que desea implementar y los coloca en el formato y la ubicación adecuados para implementarlos.

1. Para crear el recurso de DynamoDB especificado en el archivo `template.yaml`, ejecute el siguiente comando.

   ```
   sam deploy --guided
   ```

   El uso de la marca `--guided` significa que AWS SAM le mostrará instrucciones para guiarlo a lo largo del proceso de implementación. Para esta implementación, introduzca un `Stack name` de **cron-app-test-db** y acepte los valores predeterminados de todas las demás opciones mediante Entrar.

   Cuando AWS SAM haya terminado de crear el recurso de DynamoDB, debería ver el siguiente mensaje:

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

1. Para confirmar que la tabla de DynamoDB se haya creado, abra la página [Tablas](https://console.aws.amazon.com/dynamodbv2/home#tables) de la consola de DynamoDB. Debería ver una tabla llamada `MyOrderTable`.

------

Después de crear la tabla, debe agregar a continuación algunos datos de muestra para probar la aplicación. El archivo CSV `sample_data.csv` que descargó anteriormente contiene una serie de entradas de ejemplo compuestas por números de pedido, fechas e información de clientes y pedidos. Use el script de Python proporcionado `load_sample_data.py` para agregar estos datos a la tabla.

**Agregación de los datos de ejemplo a la tabla**

1. Vaya al directorio que contiene los archivos `sample_data.csv` y `load_sample_data.py`. Si estos archivos están en directorios distintos, muévalos para que se guarden en la misma ubicación.

1. Ejecute el siguiente comando para crear un entorno virtual de Python que ejecute el script: Le recomendamos que utilice un entorno virtual, ya que en el siguiente paso tendrá que instalar AWS SDK para Python (Boto3).

   ```
   python -m venv venv
   ```

1. Ejecute el siguiente comando para activar el entorno virtual.

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

1. Ejecute el siguiente comando para instalar SDK para Python (Boto3) en el entorno virtual. El script utiliza esta biblioteca para conectarse a la tabla de DynamoDB y agregar los elementos.

   ```
   pip install boto3
   ```

1. Ejecute el siguiente comando para ejecutar el script y rellenar la tabla.

   ```
   python load_sample_data.py
   ```

   Si el script se ejecuta correctamente, debería imprimir cada elemento en la consola a medida que lo carga y notificar `Data loading completed`.

1. Ejecute el siguiente comando para desactivar el entorno virtual.

   ```
   deactivate
   ```

1. Para verificar que los datos se hayan cargado en la tabla de DynamoDB, haga lo siguiente:

   1. Abra la página [Explorar elementos](https://console.aws.amazon.com/dynamodbv2/home#item-explorer) en la consola de DynamoDB y seleccione su tabla (`MyOrderTable`).

   1. En el panel **Elementos devueltos**, debería ver los 25 elementos del archivo CSV que el script agregó a la tabla.

## Creación de la aplicación con el mantenimiento programado
<a name="scheduled-task-app-create-app"></a>

Puede crear e implementar los recursos para esta aplicación de ejemplo paso a paso con la Consola de administración de AWS o mediante AWS SAM. En un entorno de producción, recomendamos que utilice una herramienta de infraestructura como código (IaC) como AWS SAM para implementar aplicaciones sin servidor repetidamente sin utilizar procesos manuales.

Para este ejemplo, siga las instrucciones de la consola para aprender a configurar cada recurso de AWS por separado o siga las instrucciones de AWS SAM para implementar la aplicación de forma rápida mediante comandos de la AWS CLI.

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

**Creación de la función con la Consola de administración de AWS**

En primer lugar, cree una función que contenga el código de inicio básico. A continuación, reemplace este código por su propio código de función, ya sea al copiar y pegar el código directamente en el editor de código de Lambda o mediante la carga del código como paquete `.zip`. Para esta tarea, le recomendamos simplemente copiar y pegar el código.

1. Abra la página de [Functions](https://console.aws.amazon.com/lambda/home#/functions) (Funciones) en la consola de Lambda.

1. Elija **Crear función**.

1. Elija **Crear desde cero**.

1. Bajo **Información básica**, haga lo siguiente:

   1. En **Nombre de la función**, introduzca `ScheduledDBMaintenance`.

   1. En **Tiempo de ejecución**, elija la versión más reciente de Python.

   1. En **Arquitectura**, elija **x86\$164**.

1. Seleccione **Creación de función**.

1. Después de crear la función, puede configurarla con el código de función proporcionado.

   1. En el panel **Código de origen**, reemplace el código Hello world que creó Lambda por el código de la función de Python del archivo `lambda_function.py` que guardó anteriormente.

   1. En la sección **IMPLEMENTAR** elija **Implementar** para actualizar el código de la función:  
![\[\]](http://docs.aws.amazon.com/es_es/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**Configuración de la memoria y el tiempo de espera de la función (consola)**

1. Seleccione la pestaña **Configuración** de la función.

1. En el panel **Configuración general**, seleccione **Editar**.

1. Establezca la **Memoria** en 256 MB y el **Tiempo de espera** en 15 segundos. Si está procesando una tabla grande con muchos registros, por ejemplo, en el caso de un entorno de producción, podría considerar la posibilidad de configurar **Tiempo de espera** con un número mayor. Esto le da a la función más tiempo para analizar y limpiar la base de datos.

1. Seleccione **Save**.

**Configuración del formato de registro (consola)**

Puede configurar las funciones de Lambda para generar registros en formato de texto no estructurado o JSON. Se recomienda utilizar el formato JSON para los registros a fin de facilitar la búsqueda y el filtrado de los datos del registro. Para obtener más información sobre las opciones de configuración de registros de Lambda, consulte [Configuración de controles de registro avanzados para las funciones de Lambda](monitoring-logs.md#monitoring-cloudwatchlogs-advanced).

1. Seleccione la pestaña **Configuración** de la función.

1. Seleccione **Herramientas de supervisión y operaciones**.

1. En el panel **Configuración de registros**, seleccione **Editar**.

1. Para la **configuración de registro**, seleccione **JSON**.

1. Seleccione **Save**.

**Configuración de permisos de IAM**

Para conceder a la función los permisos que necesita para leer y eliminar elementos de DynamoDB, debe añadir una política al [rol de ejecución](lambda-intro-execution-role.md) de la función que defina los permisos necesarios.

1. Abra la pestaña **Configuración** y, a continuación, seleccione **Permisos** en la barra de navegación izquierda.

1. Elija el nombre del rol en **Rol de ejecución**.

1. En la consola de IAM, elija **Agregar permisos** y, a continuación, **Crear política insertada**.

1. Utilice el editor de JSON e ingrese la política siguiente:  
****  

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

1. Asigne un nombre a la política **DynamoDBCleanupPolicy** y, a continuación, créela.

**Configuración del Programador de EventBridge como desencadenador (consola)**

1. Abra la [consola de EventBridge](https://console.aws.amazon.com/events/home).

1. En el panel de navegación izquierdo, elija **Programadores** en la sección **Programador**.

1. Elija **Crear programación**.

1. Para configurar la programación, haga lo siguiente:

   1. En **Nombre de la programación**, ingrese un nombre para la programación (por ejemplo, **DynamoDBCleanupSchedule**).

   1. En **Patrón de programación**, elija **Programación periódica**.

   1. En **Tipo de programación**, deje el valor predeterminado como **Programación basada en cron** e ingrese los siguientes detalles de programación:
      + **Minutos**: **0**
      + **Horas**: **3**
      + **Día del mes**: **1**
      + **Mes**: **\$1**
      + **Día de la semana**: **?**
      + **Año**: **\$1**

      Cuando se evalúa, esta expresión cron se ejecuta el primer día de cada mes a las 03:00 h.

   1. En **Intervalo de tiempo flexible**, seleccione **Desactivado**.

1. Elija **Siguiente**.

1. Para configurar el desencadenador de la función de Lambda, haga lo siguiente:

   1. En el panel **Detalle del destino**, deje la opción **API de destino** establecida en **Destinos con plantillas** y, a continuación, seleccione **Invocación de AWS Lambda**.

   1. En **Invocar**, seleccione la función de Lambda (`ScheduledDBMaintenance`) en la lista desplegable.

   1. Deje la opción **Carga útil** vacía y seleccione **Siguiente**.

   1. Desplácese hacia abajo hasta **Permisos** y seleccione **Crear un nuevo rol para esta programación**. Al crear una nueva programación del Programador de EventBridge con la consola, el Programador de EventBridge crea una nueva política con los permisos necesarios que la programación necesita para invocar la función. Para obtener más información sobre la gestión de los permisos de programación, consulte [Cron-based schedules](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html#cron-based) en la *Guía del usuario del Programador de EventBridge*.

   1. Elija **Siguiente**.

1. Revise la configuración y elija **Crear programación** para completar la creación de la programación y el desencadenador de Lambda.

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

**Implementación de la aplicación mediante AWS SAM**

1. Vaya a la carpeta en la que guardó el archivo `template.yaml` de la aplicación. Tenga en cuenta que en este ejemplo se utilizan dos archivos `template.yaml`. Asegúrese de que estén guardados en subcarpetas independientes y de que se encuentra en la carpeta correcta que contiene la plantilla para crear la aplicación.

1. Copie los archivos `lambda_function.py` y `requirements.txt` que descargó anteriormente en la misma carpeta. La ubicación del código especificada en la plantilla de AWS SAM es `./`, es decir, la ubicación actual. AWS SAM buscará en esta carpeta el código de la función de Lambda cuando intente implementar la aplicación.

1. Ejecute el siguiente comando.

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

   Este comando recopila los artefactos de compilación de los recursos que desea implementar y los coloca en el formato y la ubicación adecuados para implementarlos. Con la opción `--use-container`, la función se crea dentro de un contenedor de Docker tipo Lambda. Lo usamos aquí para que no necesite tener Python 3.12 instalado en su máquina local para que la compilación funcione.

1. Para crear los recursos de Lambda y el Programador de EventBridge especificados en el archivo `template.yaml`, ejecute el siguiente comando.

   ```
   sam deploy --guided
   ```

   El uso de la marca `--guided` significa que AWS SAM le mostrará instrucciones para guiarlo a lo largo del proceso de implementación. Para esta implementación, introduzca un `Stack name` de **cron-maintenance-app** y acepte los valores predeterminados de todas las demás opciones mediante Entrar.

   Cuando AWS SAM haya terminado de crear los recursos de Lambda y el Programador de EventBridge, debería ver el siguiente mensaje:

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

1. Para confirmar que la función de Lambda se haya creado, también puede abrir la página [Funciones](https://console.aws.amazon.com/lambda/home#/functions) de la consola de Lambda. Debería ver una función llamada `ScheduledDBMaintenance`.

------

## Pruebas de la aplicación
<a name="scheduled-task-app-test-app"></a>

 Para comprobar que la programación desencadene correctamente la función y que la función limpie correctamente los registros de la base de datos, puede modificar temporalmente la programación para que se ejecute una vez cada cierto tiempo. A continuación, puede volver a ejecutar `sam deploy` para restablecer la programación de periodicidad para que se ejecute una vez al mes. 

**Ejecución de la aplicación mediante la Consola de administración de AWS**

1. Vuelva a la página de la consola del Programador de EventBridge.

1. Elija la programación y, a continuación, elija **Editar**.

1. En la sección **Patrón de programación**, en **Recurrencia**, elija **Programación única**.

1.  Establezca la hora de invocación en unos minutos a partir de ahora, revise la configuración y, a continuación, elija **Guardar**. 

 Una vez ejecutada la programación e invocado su destino, ejecute el script `test_app.py` para comprobar que la función haya eliminado correctamente todos los registros antiguos de la tabla de DynamoDB. 

**Verificación de la eliminación de los registros antiguos mediante un script de Python**

1.  En la línea de comandos, vaya a la carpeta en la que guardó `test_app.py`. 

1. Ejecute el script.

   ```
   python test_app.py
   ```

    Si todo va bien, obtendrá el siguiente resultado. 

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

## Siguientes pasos
<a name="scheduled-task-app-next-steps"></a>

 Ahora puede modificar la programación del Programador de EventBridge para adaptarla a los requisitos específicos de su aplicación. El Programador de EventBridge admite las siguientes expresiones de programación: cron, frecuencia y única. 

 Para obtener más información sobre las expresiones de programación del Programador de EventBridge, consulte [Tipos de programación](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html) en la *Guía del usuario del Programador de EventBridge*. [Administración de acceso](https://docs.aws.amazon.com/IAM/latest/UserGuide/access.html) en la *Guía del usuario de IAM* 

# Creación de un sistema de procesamiento de pedidos con funciones duraderas de Lambda
<a name="order-processing-app"></a>

**nota**  
NECESIDAD: Añadir un diagrama de arquitectura que muestre la API Gateway, el flujo de trabajo de funciones duraderas y los servicios de soporte (DynamoDB, EventBridge).

## Requisitos previos
<a name="order-processing-prerequisites"></a>
+ AWS CLI instalado y configurado
+ NECESIDAD: Requisitos específicos de funciones duraderas.

## Creación de los archivos de código fuente
<a name="order-processing-source"></a>

Cree los siguientes archivos en el directorio del proyecto:
+ `lambda_function.py`: código de función
+ `requirements.txt`: manifiesto de dependencias

### Código de la función
<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
```

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

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

## Implementar la aplicación
<a name="order-processing-deploy"></a>

### Creación de una tabla de pedidos de DynamoDB
<a name="order-processing-dynamodb"></a>

1. Abra la consola de DynamoDB desde [ttps://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/).

1. Elija **Create table** (Crear tabla).

1. En **Nombre de la tabla**, introduzca **Orders**.

1. En **Clave de partición**, introduzca **orderId**.

1. Deje el resto de los ajustes según los valores predeterminados.

1. Elija **Create table** (Crear tabla).

### Crear la función Lambda
<a name="order-processing-lambda"></a>

1. Abra la consola de Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1. Elija **Create function (Crear función)**

1. Seleccione **Crear desde cero**.

1. En **Nombre de la función**, ingrese **ProcessOrder**.

1. En **Tiempo de ejecución**, elija el tiempo de ejecución que prefiera.

1. NECESIDAD: Añadir una configuración específica para funciones duraderas.

1. Elija **Create function (Crear función)**

### Creación del punto de conexión de API Gateway
<a name="order-processing-apigateway"></a>

1. Abra la consola de API Gateway en [https://console.aws.amazon.com/apigateway/](https://console.aws.amazon.com/apigateway/).

1. Seleccione **Crear API**.

1. Seleccione **HTTP API**.

1. Seleccione **Compilar**.

1. Añada una integración con su función de Lambda.

1. Configure rutas para el procesamiento de pedidos.

1. Implemente la API.

## Pruebe la aplicación.
<a name="order-processing-test"></a>

Envíe un pedido de prueba:

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

NECESIDAD: Añadir instrucciones de supervisión específicas para las funciones duraderas.

## Siguientes pasos
<a name="order-processing-next-steps"></a>

### Agregado de lógica empresarial
<a name="order-processing-business-logic"></a>

Implemente la gestión de inventario:

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

Añada cálculos de precios:

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

### Mejora de la gestión de errores
<a name="order-processing-error-handling"></a>

Añada lógica de compensación:

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

Gestione cancelaciones de pedidos:

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

### Integración de 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
```

### Supervisión mejorada
<a name="order-processing-monitoring"></a>
+ Cree paneles de CloudWatch.
+ Configure métricas para los tiempos de procesamiento de los pedidos.
+ Configure alertas para pedidos retrasados.