AWS CDK で EventBridge + Lambda で定期実行処理(バッチ処理)を実装してみた

2021.09.06

はじめに

プロフィールビューアーサービスProflly(プロフリー)の開発にて、定期的にデータを集計して、集計結果を保存しておく処理を、AWS CDK(TypeScript) を使って EventBridge + Lambda にて実装してみました。その定期実行処理(バッチ処理)の実装方法を紹介させていただきます。

作成するアーキテクチャ

EventBridgeを利用して月初の AM 1:00 (JST) に Lambda を定期的に実行するように作成します。

環境

  • AWS CDK 1.121.0
  • TypeScript 3.9.7

実装内容

利用するパッケージをインストール

今回作成するアーキテクチャに必要なパッケージをインストールします。

npm install --save-dev @aws-cdk/aws-dynamodb @aws-cdk/aws-lambda-nodejs @aws-cdk/aws-events @aws-cdk/aws-events-targets

スタックの実装

スタックの中で各 Construt を定義して、リソースを作成します。

lib/cdk-event-bridge-batch-sample-stack.ts

import * as cdk from '@aws-cdk/core';
import {RemovalPolicy} from '@aws-cdk/core';
import {NodejsFunction} from "@aws-cdk/aws-lambda-nodejs";
import {Table, BillingMode, AttributeType} from '@aws-cdk/aws-dynamodb';
import * as events from "@aws-cdk/aws-events";
import * as targets from '@aws-cdk/aws-events-targets';

export class CdkEventBridgeBatchSampleStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        // 集計結果を保存する DynamoDB テーブル
        const batchSampleTable = new Table(this, "batchSampleTable", {
            billingMode: BillingMode.PAY_PER_REQUEST,
            partitionKey: {
                name: "sample_id",
                type: AttributeType.NUMBER,
            },
            removalPolicy: RemovalPolicy.DESTROY
        });

        // 定期実行する Lambda 関数
        const sampleLambda = new NodejsFunction(this, "sampleLambda", {
            entry: "src/index.ts",
            handler: "handler",
            environment: {
                TABLE_NAME: batchSampleTable.tableName
            }
        });
        batchSampleTable.grantReadWriteData(sampleLambda);

        // EventBridge のルール
        new events.Rule(this, "sampleRule", {
            // JST で毎月1日の AM1:00 に定期実行
            // see https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html#CronExpressions
            schedule: events.Schedule.cron({minute: "0", hour: "16", day: "L"}),
            targets: [new targets.LambdaFunction(sampleLambda, {retryAttempts: 3})],
        });
    }
}

デプロイ後の確認

以下のコマンドでデプロイを実行し、実行結果を確認してみます。

cdk deploy

各リソースが作成されていることを確認できました。

EventBridge のルールについても、意図した通りに作成されていることを確認できました。

JSTで月末と月初の指定方法

今回は月初の AM 1:00 (JST) に定期実行したかったのですが、 Cron 式では UTC タイムゾーンで指定する必要があります。指定の際に少し迷いましたので、JSTで月初と月末を指定する際の Cron 式の例を記載しておきます。(時差を利用できる範囲で有効な方法となります) 月または週の最終日を表すワイルドカード L があるので、こちらを使うのがシンプルで楽でした。 指定方法については、公式ドキュメントにも記載がありますので、詳細はこちらをご確認下さい。

毎月1日のAM0:00に実行する場合

0 15 L * ? *

毎月月末のPM23:00に実行する場合

0 14 L * ? *

設定の確認

設定した値がいつトリガーされるのか?を確認したい場合、マネジメントコンソール上でルールを作成する際に確認することもできますので、意図した日時にトリガーされるのか?を確認することもできます。

さいごに

Lambda 関数で定期実行したい処理を作成する際は、CDK を使って Lambda + EventBridge で実装するのも手軽でいいなぁと思いました。どなたかの参考になれば幸いです。

今回サンプルで作成したソース一式は以下に配置してありますので、興味を持たれた方は実際に動かしてみてください。

参考