Aurora Serverless DB を作って Node.js(TS) から使う

## 概要

Aurora Serverless DB を作成して、
Node.js (TypeScript) からアクセスしてみます。

## 実行時の環境 2019/12/04

- MacOS 10.14.4
- node v10.15.0
- npm 6.6.0
- ts-node v8.5.4
- aws-sdk 2.584.0

## DB の作成

[Data API 公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/data-api.html)を見ると、
現在、Data API が有効なリージョンは限られているらしいので注意
[東京リージョンでつくる。](https://ap-northeast-1.console.aws.amazon.com/rds/home?region=ap-northeast-1#launch-dbinstance:gdb=false)

- DB 作成方法

| 項目                 | 値       |
| -------------------- | -------- |
| テータベース作成方法 | 標準作成 |

- エンジンのオプション

| 項目                     | 値                               |
| ------------------------ | -------------------------------- |
| エンジンのタイプ         | Amazon Aurora                    |
| エディション             | MySQL 互換                       |
| バージョン               | 現行最新: Aurora (MySQL)-5.6.10a |
| データベースロケーション | リージョン別                     |

- データベースの機能

| 項目               | 値           |
| ------------------ | ------------ |
| データベースの機能 | サーバーレス |

- 設定

  - **マスターパスワード** はあとでテストに出るのでノートにとること

- キャパシティーの設定
    - `ACU` = `Aurora キャパシティーユニット`
        - 使用する ACU x 時間に応じて課金が発生する。デフォルト最大値 128 とかいってて怖いから 8 に下げて様子見る。
    - コールドスタート
        - 使ってない時間帯は勝手に止まってくれる
        - 使い始めは 1 分かけてゆるく起動するらしい
        - 開発環境とか社内向けサービスなのでゆるくていい

| 項目     | 値                                                  |
| -------- | --------------------------------------------------- |
| 最小 ACU | 1                                                   |
| 最大 ACU | 8                                                   |
| 追加設定 | アイドルの場合、コンピューティングを一時停止: 15 分 |

- 接続
  - `Data API` を有効にする
  - そのほかはてきとう

| 項目                     | 値       |
| ------------------------ | -------- |
| ウェブサービスデータ API | Data API |

- 追加設定
  - 基本的にデフォルトのままにした。
  - `最初のデータベース名` …DB 名とは違うのか？
        - MySQL でいう `データベース` は `スキーマ` と同じと考えていいらしい
        - ややこしいわ
        - 複数のサービスで DB を利用する予定なので、はじめにのせるサービス名にした

### DB ができた

- `作成中`ステータスで表示された
- しばらくまつと `利用可能` になった

## Query Editor を使って DB にユーザーを作る

### Query Editor への接続

- RDS メニューから `Query Editor` へアクセス
  - 作成した DB を選択
  - user: admin
  - password: さっきメモっといたマスターパスワード
        - メモっとかなかったおバカさん(俺)は、DB の設定変更から再設定
- データベースに接続
- コンソールが開き、デフォルトのクエリが実行できたら OK
- せっかくなので、 `SHOW DATABASES;` してみる
  - DB 作成時に`最初のデータベース名`に入力していたデータベース(スキーマ)が表示されるはず

### 開発用ユーザーを作り、データベースへのアクセス権を与える

```sql:in-QueryEditor
CREATE USER 'devuser'@'%' IDENTIFIED BY 'YOUR_PASSWORD';
GRANT ALL ON (最初のデータベース名).* TO devuser;
```

成功を確認したら、作ったユーザーでアクセスしてみる

- 「データベースを変更する」
  - user: `devuser`
  - password: `YOUR_PASSWORD`
  - データベースまたはスキーマ: `(最初のデータベース名)`
- 接続してクエリが実行できたら OK

## Node.js から DB に接続する

これがやりたかった

[Data API 公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/data-api.html) から必要な部分を実行していく

### Data API にアクセスするためのシークレットを作る

- [Secret Manager](https://ap-northeast-1.console.aws.amazon.com/secretsmanager/home?region=ap-northeast-1#/home)から、MySQL ユーザーに対応する Secret を発行する必要がある。
- しかし、なんと Query Editor からアクセスした時点で Secret が勝手に作られている。便利。

### アクセスするサンプルコードを書いて実行してみる (TypeScript)

```typescript:src/aurora-test.ts
import { RDSDataService } from "aws-sdk";
import { ExecuteStatementRequest } from "aws-sdk/clients/rdsdataservice";

(function testQuery() {
  const rds = new RDSDataService({
    region: "ap-northeast-1",
    accessKeyId: "***",
    secretAccessKey: "***"
  });

  const params: ExecuteStatementRequest = {
    resourceArn: "***", // RDS > データベース > 設定 から参照
    secretArn: "***", // SecretManager > 追加したユーザーのSecret > シークレットのARN
    database: "(最初のデータベース名)",
    sql: "select * from information_schema.tables",
    includeResultMetadata: true
  };

  rds.executeStatement(params, (err, data) => {
    if (err) {
      console.error(err, err.stack);
    } else {
      console.log(`Fetch ${data.records!.length} rows!`);
      console.log(data.columnMetadata!.map(col => col.name).join(","));
      for (const record of data.records!) {
        console.log(record.map(col => Object.values(col)[0]).join(","));
      }
    }
  });
})();
```

`ts-node` で実行

```sh
ts-node src/aurora-test.ts

> Fetch 69 rows!
> TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,TABLE_TYPE,ENGINE,VERSION,ROW_FORMAT,TABLE_ROWS,AVG_ROW_LENGTH,DATA_LENGTH,MAX_DATA_LENGTH,INDEX_LENGTH,DATA_FREE,AUTO_INCREMENT,CREATE_TIME,UPDATE_TIME,CHECK_TIME,TABLE_COLLATION,CHECKSUM,CREATE_OPTIONS,TABLE_COMMENT
> def,information_schema,CHARACTER_SETS,SYSTEM VIEW,MEMORY,10,Fixed,true,384,0,16434816,0,0,true,2019-12-04 07:35:09,true,true,utf8_general_ci,true,max_rows=43690,
> def,information_schema,COLLATIONS,SYSTEM VIEW,MEMORY,10,Fixed,true,231,0,16704765,0,0,true,2019-12-04 07:35:09,true,true,utf8_general_ci,true,max_rows=72628,
> ...
```

## UTF-8 を指定してUnicodeを扱えるようにする
デフォルトの character set が `latin` とかいうやつで、
日本語が全部 `???` になって困ったので設定を変える。
[別記事に切り出した](https://qiita.com/tokiha0s/items/beda4be4f6815e198c76)

## SSH Tunnel (ec2踏み台) を使って直接接続する
Aurora Serverless はpublic ipを持てない。
ふつーに自由にクエリ書きたいときに困るよねってことで、
@hhrrwwttrr さんにおねがいして、踏み台EC2を作ってもらった。
踏み台を準備してもらうと、[Sequel Pro](https://www.sequelpro.com/) などのクライアントからも直接SSH経由で接続できて便利。

作る手順とかは @hhrrwwttrr さんがわかりやすく書いてくれるって言ってた。

## できあがり

認証情報の扱いにはきをつけてつかおうね