

# 定期的にデータベースメンテナンスを実行するアプリケーションを作成する
<a name="scheduled-task-app"></a>

AWS Lambda を使用して、自動システムバックアップ、ファイル変換、メンテナンスタスクなどの定期的なプロセスを置き換えることができます。この例では、古いエントリを削除して DynamoDB テーブルで定期メンテナンスを実行するサーバーレスアプリケーションを作成します。アプリケーションは EventBridge スケジューラを使用して、cron スケジュールで Lambda 関数を呼び出します。呼び出されると、関数は 1 年以上前の項目についてテーブルをクエリし、それらを削除します。関数は、削除された各項目を CloudWatch Logs に記録します。

この例を実装するには、まず DynamoDB テーブルを作成し、関数がクエリするためのテストデータを入力します。次に、EventBridge スケジューラトリガーと IAM 実行ロールを使用して Python Lambda 関数を作成し、関数にテーブルから項目を読み取って削除するアクセス許可を付与します。

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


**ヒント**  
Lambda を初めて使用する場合は、このサンプルアプリを作成する前にチュートリアル [最初の Lambda 関数を作成する](getting-started.md) を完了することをお勧めします。

AWS マネジメントコンソール を使用してリソースを作成して設定することで、アプリを手動でデプロイできます。AWS Serverless Application Model (AWS SAM) を使用してアプリケーションをデプロイすることもできます。AWS SAM は、Infrastructure as Code (IaC) ツールです。IaC では、リソースを手動で作成するのではなく、コードに定義して自動的にデプロイします。

このサンプルアプリケーションをデプロイする前に、IaC で Lambda を使用する方法の詳細については、「[Lambda と Infrastructure as code (IaC) の使用](foundation-iac.md)」を参照してください。

## 前提条件
<a name="scheduled-task-app-prereqs"></a>

サンプルアプリを作成する前に、必要なコマンドラインツールとインストールされたプログラムがあることを確認してください。
+ **Python**

  アプリケーションをテストするために作成した DynamoDB テーブルにデータを入力するために、この例では Python スクリプトと CSV ファイルを使用してテーブルにデータを書き込みます。Python バージョン 3.8 以降がマシンにインストールされていることを確認してください。
+ **AWS SAM CLI**

  AWS SAM を使用して DynamoDB テーブルを作成し、サンプルアプリをデプロイする場合は、AWS SAM CLI をインストールする必要があります。「*AWS SAM ユーザーガイド*」の「[インストール手順](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)」に従います。
+ **AWS CLI**

  提供された Python スクリプトを使用してテストテーブルに入力するには、AWS CLI をインストールして設定する必要があります。これは、スクリプトが AWS Identity and Access Management (IAM) 認証情報にアクセスする必要がある AWS SDK for Python (Boto3) を使用するためです。また、AWS SAM を使用してリソースをデプロイする場合も、AWS CLI をインストールする必要があります。「*AWS Command Line Interface ユーザーガイド*」の「[インストール手順](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」に従って CLI をインストールします。
+ **Docker**

  AWS SAM を使用してアプリケーションをデプロイするには、ビルドマシンに Docker もインストールする必要があります。Docker ドキュメントウェブサイトの「[Docker エンジンのインストール](https://docs.docker.com/engine/install/)」の手順に従います。

## サンプルアプリケーションファイルのダウンロード
<a name="scheduled-task-app-download"></a>

サンプルデータベースと定期メンテナンスアプリを作成するには、プロジェクトディレクトリに以下のファイルを作成する必要があります:

**データベースファイルの例**
+ `template.yaml` - DynamoDB テーブルの作成に使用できる AWS SAM テンプレート
+ `sample_data.csv` - テーブルにロードするサンプルデータを含む CSV ファイル
+ `load_sample_data.py` - CSV ファイル内のデータをテーブルに書き込む Python スクリプト

**定期メンテナンスアプリファイル**
+ `lambda_function.py` - データベースのメンテナンスを実行する Lambda 関数の Python 関数コード
+ `requirements.txt` - Python 関数コードに必要な依存関係を定義するマニフェストファイル
+ `template.yaml` - アプリケーションのデプロイに使用できる AWS SAM テンプレート

**テストファイル**
+ `test_app.py` - テーブルをスキャンし、1 年以上前のすべてのレコードを出力して関数が正常に動作することを確認する Python スクリプト

以下のセクションを展開してコードを表示し、アプリケーションの作成とテストにおける各ファイルの役割の詳細を確認してください。ローカルマシンにファイルを作成するには、以下のコードをコピーして貼り付けます。

### AWS SAM テンプレート (DynamoDB テーブルの例)
<a name="scheduled-task-app-table-yaml"></a>

次のコードをコピーし、`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
```

**注記**  
AWS SAM テンプレートは、`template.yaml` の標準の命名規則を使用します。この例では、2 つのテンプレートファイルがあります。1 つはサンプルデータベースを作成するもので、もう 1 つはアプリケーション自体を作成するものです。プロジェクトフォルダ内の個別のサブディレクトリに保存します。

この AWS SAM テンプレートは、アプリケーションをテストするために作成する DynamoDB テーブルリソースを定義します。テーブルでは、`Date` のソートキーと一緒に `Order_number` のプライマリキーを使用します。Lambda 関数を日付によって項目を直接検索できるように、`Date-index` という名前の[グローバルセカンダリインデックス](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html)も定義します。

`AWS::DynamoDB::Table` リソースを使用した DynamoDB テーブルの作成と設定の詳細については、「*AWS CloudFormation ユーザーガイド*」の「[AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)」を参照してください。

### サンプルデータベースデータファイル
<a name="scheduled-task-app-csv-file"></a>

次のコードをコピーし、`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
```

このファイルには、DynamoDB テーブルに標準のカンマ区切り (CSV) フォーマットで入力するためのテストデータの例が含まれています。

### サンプルデータをロードする Python スクリプト
<a name="scheduled-task-app-load-script"></a>

次のコードをコピーし、`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.")
```

この Python スクリプトは、まず AWS SDK for Python (Boto3) を使用して DynamoDB テーブルへの接続を作成します。次に、サンプルデータ CSV ファイル内の各行を繰り返し、その行から項目を作成し、boto3 SDK を使用してその項目を DynamoDB テーブルに書き込みます。

### Python 関数コード
<a name="scheduled-task-app-function-code"></a>

次のコードをコピーし、`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'
    }
```

Python 関数コードには、関数が呼び出されたときに Lambda が実行する[ハンドラー関数](python-handler.md) (`lambda_handler`) が含まれています。

EventBridge スケジューラによって関数が呼び出されると、AWS SDK for Python (Boto3) を使用して、定期メンテナンスタスクを実行する DynamoDB テーブルへの接続を作成します。次に、Python `datetime` ライブラリを使用して 1 年前の日付を計算し、これより古い項目についてテーブルをスキャンして削除します。

DynamoDB クエリおよびスキャンオペレーションからの応答は、最大 1 MB のサイズに制限されることに注意してください。レスポンスが 1 MB より大きい場合、DynamoDB はデータをページ分割し、レスポンスに `LastEvaluatedKey` 要素を返します。関数がテーブル内のすべてのレコードを処理するように、このキーがあるかを確認し、テーブル全体がスキャンされるまで、最後に評価された位置からテーブルスキャンを続行します。

### `requirements.txt` マニフェストファイル
<a name="scheduled-task-app-dependencies"></a>

次のコードをコピーし、`requirements.txt` という名前のファイルに貼り付けます。

```
boto3
```

この例では、関数コードには、標準の Python ライブラリに含まれていない依存関係が 1 つだけあります - DynamoDB テーブルから項目をスキャンして削除するために関数が使用する SDK for Python (Boto3)。

**注記**  
SDK for Python (Boto3) のバージョンは Lambda ランタイムの一部として含まれているため、Boto3 を関数のデプロイパッケージに追加せずにコードが実行されます。ただし、関数の依存関係を完全に制御し、バージョン不一致による問題を回避するには、Python のベストプラクティスとして、関数のデプロイパッケージにすべての関数の依存関係を含めることをお勧めします。詳細については、「[Python でのランタイム依存関係](python-package.md#python-package-dependencies)」を参照してください。

### AWS SAM テンプレート (定期メンテナンスアプリケーション)
<a name="scheduled-task-app-table-yaml"></a>

次のコードをコピーし、`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
```

**注記**  
AWS SAM テンプレートは、`template.yaml` の標準の命名規則を使用します。この例では、2 つのテンプレートファイルがあります。1 つはサンプルデータベースを作成するもので、もう 1 つはアプリケーション自体を作成するものです。プロジェクトフォルダ内の個別のサブディレクトリに保存します。

この AWS SAM テンプレートは、アプリケーションのリソースを定義すします。`AWS::Serverless::Function` リソースを使用して Lambda 関数を定義します。EventBridge スケジューラのスケジュールと Lambda 関数を呼び出すトリガーは、`ScheduleV2` のタイプを使用しているこのリソースの `Events` プロパティを使用して作成されます。AWS SAM テンプレートでの EventBridge スケジューラのスケジュールの定義の詳細については、「*AWS Serverless Application Model デベロッパーガイド*」の「[ScheduleV2](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-schedulev2.html)」を参照してください。

Lambda 関数と EventBridge スケジューラのスケジュールに加えて、削除された項目のレコードを送信する関数の CloudWatch ロググループも定義します。

### テストスクリプト
<a name="scheduled-task-app-test-script"></a>

次のコードをコピーし、`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)}")
```

このテストスクリプトは、AWS SDK for Python (Boto3) を使用して DynamoDB テーブルへの接続を作成し、1 年以上前の項目をスキャンします。Lambda 関数が正常に実行されたかどうかを確認するには、テストの最後に、関数はテーブルに残っている 1 年以上前のレコードの数を出力します。Lambda 関数が成功した場合、テーブル内の古いレコードの数はゼロになっているはずです。

## DynamoDB のサンプルテーブルの作成と入力
<a name="scheduled-task-app-create-table"></a>

定期メンテナンスアプリケーションをテストするには、まず DynamoDB テーブルを作成し、いくつかのサンプルデータを入力します。テーブルは、AWS マネジメントコンソール を使用して手動で作成することも、AWS SAM を使用して作成することもできます。AWS SAM を使用して、いくつかの AWS CLI コマンドでテーブルをすばやく作成および設定することをお勧めします。

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

**DynamoDB テーブルを作成する**

1. DynamoDB コンソールで [[テーブル]](https://console.aws.amazon.com/dynamodbv2/home#tables) ページを開きます。

1. **[テーブルの作成]** を選択します。

1. 以下の操作でテーブルを作成します:

   1. **[テーブルの詳細]** の **[テーブル名]** に **MyOrderTable** を入力します。

   1. **[パーティションキー]** に **Order\$1number** と入力し、型を **[文字列]** のままにします。

   1. **[ソートキー]** に、**Date** と入力し、型を **[文字列]** のままにします。

   1. **[テーブル設定]** を **[デフォルト設定]** に設定したままにして、**[テーブルの作成]** を選択します。

1. テーブルの作成が完了し、その **[ステータス]** が **[アクティブ]** と表示されたら、以下を実行してグローバルセカンダリインデックス (GSI) を作成します。アプリケーションは、この GSI を使用して日付で項目を直接検索し、削除する項目を決定します。

   1. テーブルのリストから **[MyOrderTable]** を選択します。

   1. **[インデックス]** タブを選択します。

   1. **[グローバルセカンダリインデックス]** で、**[インデックスの作成]** を選択します。

   1. **[インデックスの詳細]** で、**[パーティションキー]**に **Date** を入力し、**[データ型]** を **[文字列]** に設定したままにします。

   1. **[Index name]** (インデックス名) に **Date-index** と入力します。

   1. 他のすべてのパラメータをデフォルト値に設定したまま、ページの下部までスクロールし、**[インデックスの作成]** を選択します。

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

**DynamoDB テーブルを作成する**

1. DynamoDB テーブルの `template.yaml` ファイルを保存したフォルダに移動します。この例では 2 つの `template.yaml` ファイルを使用することに注意してください。それらが別々のサブフォルダに保存され、DynamoDB テーブルを作成するためのテンプレートを含む正しいフォルダに格納されていることを確認します。

1. 以下のコマンドを実行してください。

   ```
   sam build
   ```

   このコマンドによって、デプロイするリソースのビルドアーティファクトが収集され、それらをデプロイする適切な形式と場所に配置します。

1. `template.yaml` ファイルで指定された DynamoDB リソースを作成するには、以下のコマンドを実行します。

   ```
   sam deploy --guided
   ```

   `--guided` フラグを使用すると、AWS SAM にデプロイプロセスの手順が示されます。このデプロイでは、**cron-app-test-db** の `Stack name` を入力し、Enter を使用して他のすべてのオプションのデフォルトを受け入れます。

   AWS SAM が DynamoDB リソースの作成を完了すると、以下のメッセージが表示されます。

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

1. さらに、DynamoDB コンソールの[テーブル](https://console.aws.amazon.com/dynamodbv2/home#tables)ページを開くことで、DynamoDB テーブルが作成されたことを確認できます。`MyOrderTable` という名前のテーブルが表示されます。

------

テーブルを作成したら、次にサンプルデータを追加してアプリケーションをテストします。先ほどダウンロードした CSV ファイル `sample_data.csv` には、注文番号、日付、顧客および注文情報で構成される多数のサンプルエントリが含まれています。このデータをテーブルに追加するには、提供された Python スクリプト `load_sample_data.py` を使用します。

**サンプルデータをテーブルに追加するには**

1. `sample_data.csv` と `load_sample_data.py` ファイルが含まれているディレクトリに移動します。これらのファイルが別のディレクトリにある場合は、同じ場所に保存されるようにファイルを移動します。

1. Python の仮想環境を作成してスクリプトを実行するには、以下のコマンドを実行します。以下のステップでは AWS SDK for Python (Boto3) をインストールする必要があるため、仮想環境を使用することをお勧めします。

   ```
   python -m venv venv
   ```

1. 以下のコマンドを実行して、仮想環境を有効にします。

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

1. 以下のコマンドを実行して、SDK for Python (Boto3) を仮想環境にインストールします。スクリプトは、このライブラリを使用して DynamoDB テーブルに接続し、項目を追加します。

   ```
   pip install boto3
   ```

1. 以下のコマンドの実行によってスクリプトを実行し、テーブルに入力します。

   ```
   python load_sample_data.py
   ```

   スクリプトが正常に実行される場合は、ロードして `Data loading completed` を報告するときに、各項目をコンソールに出力する必要があります。

1. 以下のコマンドを実行して、仮想環境を無効にします。

   ```
   deactivate
   ```

1. データを DynamoDB テーブルにロードしたことを確認するには、以下の手順を実行します。

   1. DynamoDB コンソールの [[項目を探す]](https://console.aws.amazon.com/dynamodbv2/home#item-explorer) ページを開いて、テーブル (`MyOrderTable`) を選択します。

   1. **[返された項目]** ペインには、スクリプトがテーブルに追加した CSV ファイルから 25 個の項目が表示されているはずです。

## 定期メンテナンスアプリケーションの作成
<a name="scheduled-task-app-create-app"></a>

このサンプルアプリケーションのリソースは、AWS マネジメントコンソール または AWS SAM を使用して着実に作成およびデプロイできます。本番環境では、手動プロセスを使用せずにサーバーレスアプリケーション繰り返しデプロイするために、AWS SAM のような Infrustracture-as-Code (IaC) ツールを使用することをお勧めします。

この例では、コンソールの指示に従って各 AWS リソースを個別に設定する方法を学習するか、AWS SAM の指示に従って、AWS CLI のコマンドを使用してアプリをすばやくデプロイします。

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

**AWS マネジメントコンソール を使用して関数を作成するには**

まず、基本的なスターターコードを含む関数を作成します。次に、Lambda コードエディタでコードを直接コピーして貼り付けるか、コードを `.zip` パッケージとしてアップロードして、このコードを独自の関数コードに置き換えます。このタスクでは、コードをただコピーして貼り付けることをお勧めします。

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. **関数の作成** を選択します。

1. **Author from scratch** を選択します。

1. **基本的な情報** で、以下の作業を行います。

   1. **[関数名]** に「`ScheduledDBMaintenance`」と入力します。

   1. **[ランタイム]** では、最新の Python バージョンを選択します。

   1. **[アーキテクチャ]** で **[x86\$164]** を選択します。

1. [**関数の作成**] を選択してください。

1. 関数を作成したら、指定された関数コードを使用して関数を設定できます。

   1. **[コードソース]** ペインで、Lambda が作成した Hello world コードを、前に保存した `lambda_function.py` ファイルの Python 関数コードに置き換えます。

   1. **[DEPLOY]** セクションで、**[デプロイ]** を選択して関数のコードを更新します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**関数のメモリとタイムアウトを設定するには (コンソール）**

1. 関数の **[設定]** タブを選択します。

1. **[一般設定]** ペインで、**[編集]** を選択します。

1. **[メモリ]** を 256 MB に設定し、**[タイムアウト]**を 15 秒に設定します。例えば本番環境のように、多数のレコードを含む大きなテーブルを処理する場合は、**[タイムアウト]**をより大きな数に設定することを検討してください。これにより、関数がデータベースをスキャンしてクリーンにするための時間が長くなります。

1. **[保存]** を選択します。

**ログ形式を設定するには (コンソール）**

Lambda 関数を設定して、非構造化テキスト形式または JSON 形式でログを出力できます。ログデータの検索とフィルタリングを容易にするために、ログには JSON 形式を使用することをお勧めします。Lambda ログ設定オプションの詳細については、「[Lambda 関数の高度なログ記録コントロールの設定](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)」を参照してください。

1. 関数の **[設定]** タブを選択します。

1. **[モニタリングおよび運用ツール]** を選択します。

1. **[ログ記録設定]** ペインで、**[編集]** を選択します。

1. **[ログ記録設定]** で、**[JSON]**を選択します。

1. **[保存]** を選択します。

**IAM 許可をセットアップするには**

関数に DynamoDB 項目の読み取りと削除に必要なアクセス許可を付与するには、必要なアクセス許可を定義するポリシーを関数の[実行ロール](lambda-intro-execution-role.md)に追加する必要があります。

1. **[設定]** タブを開き、左側のナビゲーションバーから **[アクセス許可]** を選択します。

1. **[実行ロール]** の下にあるロール名を選択します。

1. IAM コンソールで、**[アクセス許可を追加]** を選択し、次いで **[インラインポリシーを作成]** を選択します。

1. JSON エディタを使用して、以下のポリシーを入力します:  
****  

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

1. ポリシー **DynamoDBCleanupPolicy** に名前を付け、作成します。

**EventBridge スケジューラをトリガーとして設定するには (コンソール)**

1. [[EventBridge コンソール](https://console.aws.amazon.com/events/home)] を開きます。

1. 左側のナビゲーションペインで、**[スケジューラ]** セクションの下の **[スケジューラ]** を選択します。

1. **[スケジュールを作成]** を選択します。

1. 以下を実行してスケジュールを設定します:

   1. **[スケジュール名]** の下で、スケジュールの名前を入力します (例えば、**DynamoDBCleanupSchedule**)。

   1. **[スケジュールパターン]** の下で **[定期的なスケジュール]** を選択します。

   1. **[スケジュールタイプ]** では、デフォルトを **[Cron ベースのスケジュール]** のままにし、以下のスケジュールの詳細を入力します:
      + **[分]**: **0**
      + **[時間]**: **3**
      + **[月日]**: **1**
      + **[月]**: **\$1**
      + **[曜日]**: **?**
      + **[年]**: **\$1**

      この cron 式は評価されると、毎月 1 日午前 3 時に実行されます。

   1. **[フレキシブルタイムウィンドウ]** で **[オフ]** を選択します。

1. [**次へ**] を選択します。

1. 以下を実行して Lambda 関数のトリガーを設定します:

   1. **[ターゲットの詳細]** ペインで、**[ターゲット API]** を **[テンプレート化されたターゲット]** に設定したまま、**[AWS Lambda の呼び出し]** を選択します。

   1. **[呼び出す]** で、ドロップダウンリストから [Lambda 関数 (`ScheduledDBMaintenance`)] を選択します。

   1. **[ペイロード]** を空のままにして、**[次へ]** を選択します。

   1. **[アクセス許可]** までスクロールダウンし、**[このスケジュールの新しいロールを作成する]** を選択します。コンソールを使用して新しい EventBridge スケジューラのスケジュールを作成すると、EventBridge スケジューラは、スケジュールが関数を呼び出すために必要なアクセス許可を持つ新しいポリシーを作成します。スケジュール許可の管理の詳細については、「*EventBridge スケジューラユーザーガイド*」の「[Cron ベースのスケジュール](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html#cron-based)」を参照してください。

   1. [**次へ**] を選択します。

1. 設定を確認し、**[スケジュールを作成]** を選択してスケジュールと Lambda トリガーの作成を完了します。

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

**AWS SAM を使用してアプリケーションをデプロイするには**

1. アプリケーションの `template.yaml` ファイルを保存したフォルダに移動します。この例では 2 つの `template.yaml` ファイルを使用することに注意してください。これらは別々のサブフォルダに保存され、アプリケーションを作成するためのテンプレートを含む正しいフォルダに保存されていることを確認します。

1. 以前にダウンロードした `lambda_function.py` および `requirements.txt` ファイルを同じフォルダにコピーします。AWS SAM テンプレートで指定されたコードの場所は `./` です。つまり、現在の場所です。アプリのデプロイを試みると、AWS SAM はこのフォルダで Lambda 関数コードを検索します。

1. 以下のコマンドを実行してください。

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

   このコマンドによって、デプロイするリソースのビルドアーティファクトが収集され、それらをデプロイする適切な形式と場所に配置します。`--use-container` オプションを指定すると、Lambda のような Docker コンテナ内に関数がビルドされます。ここではこれを使用するため、ビルドを実行するためにローカルマシンに Python 3.12 をインストールする必要はありません。

1. `template.yaml` ファイルで指定された Lambda および EventBridge スケジューラリソースを作成するには、以下のコマンドを実行します。

   ```
   sam deploy --guided
   ```

   `--guided` フラグを使用すると、AWS SAM にデプロイプロセスの手順が示されます。このデプロイでは、**cron-maintenance-app** の `Stack name` を入力し、Enter を使用して他のすべてのオプションのデフォルトを受け入れます。

   AWS SAM が Lambda および EventBridge スケジューラリソースの作成を完了すると、以下のメッセージが表示されるはずです。

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

1. さらに、Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開くことで、Lambda 関数が作成されたことを確認できます。`ScheduledDBMaintenance` という名前の関数が表示されるはずです。

------

## アプリのテスト
<a name="scheduled-task-app-test-app"></a>

 スケジュールが関数を正しくトリガーし、関数がデータベースからレコードを正しくクリーンアップすることをテストするには、スケジュールを一時的に変更して、特定の時間に 1 回実行するようにします。その後、`sam deploy` を再度実行して、毎月 1 回実行するように繰り返しスケジュールをリセットできます。

**AWS マネジメントコンソール を使用してアプリケーションを実行するには**

1. EventBridge スケジューラコンソールページに戻ります。

1. スケジュールを選択してから、**[編集]** を選択します。

1. **[スケジュールパターン]** セクションの **[繰り返し]** の下にある **[1 回限りのスケジュール]** を選択します。

1.  呼び出し時間を数分後に設定し、設定を確認してから **[保存]** を選択します。

 スケジュールが実行され、ターゲットが呼び出されたら、`test_app.py` スクリプトを実行して、関数が DynamoDB テーブルから古いレコードをすべて正常に削除したことを確認します。

**古いレコードが Python スクリプトを使用して削除されていることを確認するには**

1.  コマンドラインで、`test_app.py` を保存したフォルダに移動します。

1. スクリプトを実行します。

   ```
   python test_app.py
   ```

    成功すると、以下の出力が表示されます。

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

## 次のステップ
<a name="scheduled-task-app-next-steps"></a>

 特定のアプリケーション要件を満たすために、EventBridge スケジューラのスケジュールを変更できるようになりました。EventBridge スケジューラは、以下のスケジュール式をサポートしています: cron、レート、1 回限りのスケジュール。

 EventBridge スケジューラのスケジュール式に関する詳細については、「*EventBridge スケジューラユーザーガイド*」の「[スケジュールタイプ](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html)」を参照してください。*IAM ユーザーガイド*の[アクセス管理](https://docs.aws.amazon.com/IAM/latest/UserGuide/access.html) 