AppSync のキャッシュを利用する

## 概要
Appsyncで、Elastichacheを使用したキャッシュが利用できるので試す。公式ドキュメントでも情報が少なかったので実際に使用してみた。


- 公式ドキュメント：https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/enabling-caching.html
- 料金：https://aws.amazon.com/jp/appsync/pricing/

## Appsyncのキャッシュ方式
Appsyncでは、キャッシュについて、以下の方法をとることが可能。以下公式ドキュメントより引用

- なし
>サーバー側のキャッシュはありません。

- 完全なリクエストのキャッシュ
>データがキャッシュにない場合は、データソースから取得され、TTL の有効期限が切れるまでキャッシュに入力されます。API への後続のリクエストはすべてキャッシュから返されます。つまり、TTL の有効期限が切れるまでデータソースに直接問い合わせることはありません。この設定でのキャッシュキーとして、\$context.arguments および \$context.identity マップのコンテンツを使用します。

- リゾルバーごとのキャッシュ
> この設定では、レスポンスをキャッシュするために、各リゾルバーを明示的にオプトインする必要があります。TTL とキャッシュキーはリゾルバーで指定できます。指定できるキャッシュキーは、\$context.arguments および \$context.identity マップの値です。TTL 値は必須ですが、キャッシュキーはオプションです。キャッシュキーが指定されていない場合、上記と同様に、デフォルトは \$context.arguments および \$context.identity マップのコンテンツになります。たとえば、\$context.arguments.id または \$context.arguments.InputType.id や、\$context.identity.sub または \$context.identity.claims.username を使用できます。キャッシュキーが指定されておらず、TTL のみの場合、リゾルバーの動作は上記と同様です。


## Cacheを利用してみる
### サンプルプロジェクトの作成（イベントアプリ）
- AWSコンソール上から、APIを作成 → サンプルプロジェクトから開始する → イベントアプリを選択し、サンプルプロジェクトを作成する

- スキーマ定義を一部抜粋

```graphql
type Event {
	id: ID!
	name: String
	where: String
	when: String
	description: String
	# Paginate through all comments belonging to an individual post.
	comments(limit: Int = 10, nextToken: String): CommentConnection
}

type EventConnection {
	items: [Event]
	nextToken: String
}

type Mutation {
	# Create a single event.
	createEvent(
		name: String!,
		when: String!,
		where: String!,
		description: String!
	): Event
	# Delete a single event by id.
	deleteEvent(id: ID!): Event
	# Comment on an event.
	commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment
}

type Query {
	# Get a single event by id.
	getEvent(id: ID!): Event
	# Paginate through events.
	listEvents(filter: TableEventFilterInput, limit: Int = 10, nextToken: String): EventConnection
}

schema {
	query: Query
	mutation: Mutation
	subscription: Subscription
}
```

### キャッシュの作成
- awsコンソール上のCachingメニューを選択し、キャッシュの選択画面を表示
- ここでは、下記の設定でキャッシュを作成する
    - Caching behavior：Per-resolver caching（リゾルバーごとのキャッシュ）
    - インスタンスタイプ：cache.small
    - キャッシュの有効期限 (TTL)：60
    - 転送時、保管時の暗号化の設定も可能。今回は特に設定を行わない

- ここで作成したキャッシュインスタンスは Appsync により管理されており、Amazon ElastiCache のコンソール上には特に存在しない

### リゾルバーの設定
- キャッシュ作成時に、「Per-resolver caching」を選択した場合は、フィールドにアタッチするリゾルバーごとにキャッシュの設定が可能となる
- Caching behavior に 「Full request caching」 を選択した場合は、リゾルバー個別の設定は不要となる

- 今回はQueryの listEventsに対して、キャッシュを有効化してみる

```
type Query {
	# Paginate through events.
	listEvents(filter: TableEventFilterInput, limit: Int = 10, nextToken: String): EventConnection
}
```

- スキーマ定義から Query → listEvents の設定済みのリゾルバーをクリック
- 画面一番下のキャッシュ設定から、キャッシュの有効化を行い、設定を保存する
![スクリーンショット 2021-03-21 20.20.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366054/697201c0-12be-2796-d045-9509c27f5e76.png)


## クエリを実行してみる
- 何度かミューテーションにて Eventを登録した後、クエリ ListEvents の実行を、数回行ってみる

```
query ListEvents {
  listEvents {
    items {
      name
      id
    }
  }
}
```

### キャッシュの利用状況のモニタリング
- AWS コンソールの Monitoringメニューから、キャッシュの利用状況の確認が可能（青いグラフががキャッシュヒットの回数）

![スクリーンショット 2021-03-21 21.01.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366054/04d10887-1534-25d8-8397-ecabd7cb26f2.png)

## あとがき
- Graphql自体において、どういう条件だとキャッシュが利用されるかについて理解していないので、調べる。（同一のクエリだと利用される？クエリの引数が異なるとキャッシュの利用はされない？等）


## 参考
- https://www.ragate.co.jp/blog/articles/6025
- https://aws.amazon.com/jp/blogs/news/appsync-caching-transactions/