【AWS】Lambda関数を隔週(2週間ごと)で自動実行する

# はじめに

AWS Lambdaの関数を隔週で実行する方法を模索した際のメモ。
CloudWatch Eventでは隔週や隔月のスケジュールで処理をトリガーするcron式が記述できないため、方法を工夫する必要があった。
以下、３パターンの方法を紹介する。

# 方法１ CloudWatch Event（cron式による毎週実行） + Lambda関数コード内で隔週判定

- CloudWatch Eventで、Lambda関数を毎週実行するルールを作成、実行スケジュールはcron式で定義。
- ルールによりトリガーされるLambda関数側では、Lambda関数コード内で実際に実行したい処理の手前に隔週判定処理を記述し、隔週日のみ実行したい処理を行うようにする。

### 設定例

2019年4月26日(金)を基準日として隔週金曜18時(JST)にLambda関数「MyLambdaFunc1」(Pythonランタイム)を実行する場合

##### CloudWatch Event

毎週金曜日18時(JST)にLambda関数「MyLambdaFunc1」を実行するルール「MyRule1」を作成

```shell
$ aws events put-rule --schedule-expression "cron(0 9 ? * FRI *)" --name MyRule1
$ aws events put-targets --rule MyRule1 --targets MyLambdaFunc1
```

##### Lambda

Lambda関数「MyLambdaFunc1」のコード内の実際に実行したい処理の手前に、関数実行日が2019年4月26日から偶数週経過した日である場合は処理を継続、奇数週経過した日である場合は処理を終了させる隔週判定処理を記述

```lambda_function.py
from datetime import datetime

def lambda_handler(event, context):

    ## 隔週判定処理 ##
    if (datetime.now() - datetime.strptime('2019/4/26', '%Y/%m/%d')).days % 14 != 0:
        return()

    ## 以降、隔週で実行したい処理 ##
```


# 方法２ API Gateway + 外部のスケジュール機能（例：Microsoft Flow）

- API GatewayでLambda関数のトリガーとなるAPIを作成、デプロイして外部からアクセス可能とする
- Microsoft Flowで隔週でAPI Gatewayにアクセスするフローを作成する

### 設定例

隔週金曜18時(JST)にLambda関数「MyLambdaFunc2」を実行する場合

##### API Gateway

Lambda関数「MyLambdaFunc2」のトリガーとなるAPIを作成。デプロイしたAPIのエンドポイントURIと、APIキー認証を設定した場合はキーの値を控えておく。
APIはGUIから作成しても良いが、私の[過去記事の方法](https://qiita.com/r-wakatsuki/items/da9cf517124ca9a6351b) で一発で作成することも可能。

```shell
///過去記事の方法///
$ function_name=MyLambdaFunc2
$ aws lambda invoke --function-name agdep --payload {\"functionName\":\"${function_name}\"} outfile;cat outfile | jq .;rm outfile

///実行結果に作成されたAPIのエンドポイントURIとAPIキーが出力される///
[
  "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/test-func_api_rsc",
  "XXXXXXXXXXXXXXXXXXXX"
]
```

##### Microsoft Flow

[Microsoft Flow](https://japan.flow.microsoft.com/ja-jp/)でフローを新規作成し、繰り返しトリガーを以下のように設定。

|プロパティ名|値|説明|
|---|---|---|
|間隔|*2*|
|頻度|*週*|
|タイム ゾーン|任意のタイムゾーン|
|開始時刻|現在日時以降で、フローを初回に実行させたい日時以前の任意の日時|※`yyyy-MM-ddTHH:mm:ss.sss`形式。時刻末尾に`Z`は不要|
|設定曜日|*金曜日*|
|設定時刻(時間)|*18*|
|設定時刻(分)|*0*|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258416/bcdb117c-3d98-78d2-f870-8a1d01321c61.png)

HTTPアクションを以下のように設定。

|プロパティ名|値|説明|
|---|---|---|
|方法|*POST*|
|URI| APIエンドポイントURI |API GatewayでAPI作成時に取得したURIを指定|
|ヘッダー|*{"x-api-key": "API認証キー"}*|※API GatewayでAPIキー認証を設定した場合のみ。API作成時に取得したAPIキーを`x-api-key`ヘッダーで指定|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258416/f43133fd-00c2-d750-6367-f25fee9ec266.png)

# 方法３  CloudWatch Event（rate式による隔週実行）

- CloudWatch Eventで、Lambda関数を隔週で実行するルールを作成、実行スケジュールはrate式で定義。（ルールの初回実行タイミング=スケジュール開始タイミングは指定できず、ルールを作成したタイミングで初回実行とスケジュールの開始が行われるため、ルールの作成方法を工夫する必要がある）

### 設定例

ルール作成時および作成時から隔週でLambda関数「MyLambdaFunc3」を実行する場合

##### CloudWatch Event

隔週でLambda関数「MyLambdaFunc3」を実行するルール「MyRule3」を作成

```shell
$ aws events put-rule --schedule-expression "rate(5 minutes)" --name MyRule3
$ aws events put-targets --rule MyRule3 --targets MyLambdaFunc3
```

# 参考

https://qiita.com/BarutanGNE/items/b14bef93c004f90c0ce4
https://qiita.com/wonder_zone/items/a15ee2760a1d9e796b67
https://docs.aws.amazon.com/cli/latest/reference/events/index.html
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html