逆引き Serverless Framework events for AWS

最近、既存の lambda を全て Serverless Framework を使って置き換えました。
Lambda は色んな event をトリガーにできるのですが記述方法を毎度ど忘れしてしまい、調べ直すことがあったのでメモを残します。もちろんこれで網羅しているわけではないので気づいたことあればご指摘ください。

# serverless.yml
ざっくりと基本構成について。

以下のように外部ファイルに値を定義している方法についてはこちらを参照
`${file(../variables-${self:provider.stage}.yml), file(../variables-dev.yml)}` 
 [Serverless Framework + Kotlin + Gradle で Lambda をデプロイする - Qiita](https://qiita.com/Nabesuke/items/40139ee441a33cb1dcf2#custom)

```serverless.yml
service: my-service # サービス名

provider: # 各functionの共通設定
  name: aws
  runtime: java8
  stage: ${opt:stage, self:custom.defaultStage}
  region: ap-northeast-1
  role: ${self:custom.settings.role}
  vpc:
    securityGroupIds:
      - ${self:custom.settings.vpc.securitygroup}
    subnetIds:
      - ${self:custom.settings.vpc.subnet}
  memorySize: 512

custom: # カスタム値を定義する場合はこちら
  defaultStage: dev
  settings: ${file(../variables-${self:provider.stage}.yml), file(../variables-dev.yml)}

package: # deployするjarを指定
  artifact: ../../build/libs/my-service.jar

functions: # lambda関数を定義する
  TestHandler:
    timeout: 20
    handler: jp.dev.edamame.test.TestHandler
    name: TestHandler
    # 今回はこの lambda関数 をトリガーする events について
    events: ${file(./job_enqueue_handler.yml):events}
```


※ コールドスタートする java runtime をlambdaで使用するのはあまり効率がいいとは言えませんが、考えあってのことです。

- 参考
[Serverless - AWS Lambda - Events](https://www.serverless.com/framework/docs/providers/aws/events/)


# S3 event
- eventsに `s3` を指定する
- S3でObjectが作成されたタイミングでLambdaを実行したいときに

```serverless.yml
    events:
      - s3: # s3 event
          bucket: jp.co.valus.test
          event: s3:ObjectCreated:*
          rules:
            - prefix: hoge/import
            - suffix: .csv
          existing: true
```

| KEY | DESCRIPTION |
| ---- | ---- |
| bucket  | イベントを受け取りたいbacket名を指定  |
| event | 対象のイベント(作成/更新/削除など)を指定 |
|rurles| **prefix** : ファイル名の前方一致。特定のディレクトリなどを指定したいときに使ってた<br> **sufix** : ファイル名の後方一致。拡張子を指定したいときに使ってた|
|existing|既に作成済みのbucketを使うときはtrueにする|

## s3に指定できるEventについて
- オブジェクト作成イベント

```serverless.yml
   - s3:
       event: s3:ObjectCreated:*
```

| EVENT | DESCRIPTION |
| ---- | ---- |
| s3:ObjectCreated:* |  全てのオブジェクト作成イベント。更新でもトリガーされる |
| s3:ObjectCreated:Put | 主に新規作成イベント。更新はトリガーされない |
| s3:ObjectCreated:Post | 不明 |
| s3:ObjectCreated:Copy | ファイルの複製を作成した時 |
| s3:ObjectCreated:CompleteMultipartUpload | マルチパートアップロード完了時<br>アップロードするファイルサイズが大きいときはこちらのイベント |

- オブジェクト削除イベント

```serverless.yml
   - s3:
       event: s3:ObjectRemoved:*
```

| EVENT | DESCRIPTION |
| ---- | ---- |
| s3: ObjectRemoved:* |  全てのオブジェクト削除イベント |
| s3:ObjectRemoved:Delete | オブジェクトが削除されたとき、またはバージョニングが有効なオブジェクトが完全に削除されたとき |
| s3:ObjectRemoved:DeleteMarkerCreated | バージョニングが有効なオブジェクトに対して削除マーカーが作成されたとき |

### 以下はあまり使ったこと無いが…

- オブジェクト復元イベント

| EVENT | DESCRIPTION |
| ---- | ---- |
|s3:ObjectRestore:* | S3 Glacier ストレージクラスにアーカイブされたオブジェクトの復元イベント全て |
| s3:ObjectRestore:Completed | オブジェクトの復元完了 |
| s3:ObjectRestore:Post | オブジェクト復元開始 |

# Cloudwatch Event (schedule)
- eventsに `schedule ` を指定する
- 〜分おきに起動させたり cron 指定でスケジューリングできる

```serverless.yml
    events:
    - schedule:
        name: job-hoge-cron-event
        description: 'hello world'
        rate: cron(0 16 * * ? *)
        input: '{"jobName":"hoge","accountId":10}'
        enabled: true
    - schedule:
        name: job-hoge-check-event
        description: 'hogefuga'
        rate: rate(1 minute)
        input: '{"jobName":"check","accountId":100}'
        enabled: true
```

| KEY | DESCRIPTION |
| ---- | ---- |
| name | スケジュール名(cloudwatch eventにこの名前で登録されます) |
| description | eventの説明 |
| rate | **cron(0 16 * * ? *)** : cron表記 <br> **rate(1 minute)** : 〜分毎に起動する<br> **rate(2 hours)** : 〜時間毎に起動する |
| input | 起動時に lambda関数 に渡す引数<br>key1: value1 : KEY : VALUEの形でも定義できる |


## rate() の設定の注意点
OK: rate(1 minute)
NG: rate(5 minute)

OK: rate(5 minutes)

１分以上のときは **minutes** としなければいけない(hourのときはhours)

## input
以下の形式をサポートしています。
※ 公式のサンプルから抜粋

```serverless.yml
      - schedule:
          rate: rate(10 minutes)
          enabled: false
          input:
            key1: value1
            key2: value2
            stageParams:
              stage: dev
      - schedule:
          rate: cron(0 12 * * ? *)
          enabled: false
          inputPath: '$.stageVariables'
      - schedule:
          rate: rate(2 hours)
          enabled: true
          inputTransformer:
            inputPathsMap:
              eventTime: '$.time'
            inputTemplate: '{"time": <eventTime>, "key1": "value1"}'
```


# SQS Queues Event
- eventsに `sqs ` を指定する
- SQSキューにメッセージがある場合に関数がトリガーされる

```serverless.yml
    events:
      - sqs:
          arn:aws:sqs:region:XXXXXX:MyFirstQueue
          batchSize: 10
```

| KEY | DESCRIPTION |
| ---- | ---- |
| arn | イベントをトリガーしたいsqsのARN |
| batchSize | 一度に送信されるメッセージの数<br>default:10<br>max: 10 |

※ 色んな記述方法があるが上記のフォーマット以外試したことない

# SNS Event
- eventsに `sns` を指定する
- メッセージが対象のSNSトピックに送信されるたびに呼び出される

```serverless.yml
events:
  - sns: dispatch
  - sns:
      arn: arn:xxx
      displayName: display name
		filterPolicy:
        pet:
          - dog
          - cat
		redrivePolicy:
            deadLetterTargetArn: arn:aws:sqs:us-east-1:11111111111:myDLQ

```

| KEY | DESCRIPTION |
| ---- | ---- |
| arn | 既存のトピックを追加する場合はarnを指定する |
| displayName |  AWSコンソール上でのトピック表示名 |
| filterPolicy | フィルターを定義する。<br>サンプルは key が pet の value が dog/cat のメッセージ以外は除外する |
| redrivePolicy | 関連付けられたLambdaの処理が失敗したときにメッセージを送るデッドレターキューを指定する |

- 新規作成して追加する場合

| KEY | DESCRIPTION |
| ---- | ---- |
| - sns: snsName | 新しいSNSトピックを作成して追加 |b

- sns 定義 サンプル

```serverless.yml
resources:
  Resources:
    myDLQ:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: myDLQ
        VisibilityTimeout: 90 # メッセージ配信後に90秒間は利用できないようにする

    SuperTopic:
      Type: AWS::SNS::Topic
      Properties:
        TopicName: MyCustomTopic
```


# その他
ほかにも色々あるが、とりあえずは使っているもののみ。
また何か試したら追記します。