`laravel-dynamodb`でキャパシティモードをオンデマンドモードにする

## はじめに

弊社のいくつかのサービスではDynamoDBを使用しています。
それらのサービスはLaravelで実装されているものが多く、 `laravel-dynamodb` というパッケージを使用しています。

## `laravel-dynamodb` とは

https://github.com/baopham/laravel-dynamodb

DynamoDBをEloquent Modelのように扱えるようにしてくれるORMのパッケージです。

https://tech.willgate.co.jp/entry/2018/02/28/134537

また、上の記事を参考にDynamoDBもマイグレーションで管理するようにしました。
(特に以下を参考にさせていただきました)
- [マイグレーションは RDBMS と区別しない](https://tech.willgate.co.jp/entry/2018/02/28/134537#%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF-RDBMS-%E3%81%A8%E5%8C%BA%E5%88%A5%E3%81%97%E3%81%AA%E3%81%84)
- [環境をまたいでテーブル名を一意にする方法](https://tech.willgate.co.jp/entry/2018/02/28/134537#%E7%92%B0%E5%A2%83%E3%82%92%E3%81%BE%E3%81%9F%E3%81%84%E3%81%A7%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%90%8D%E3%82%92%E4%B8%80%E6%84%8F%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)

## 今回の問題

弊社サービスの現状では、キャパシティモードの調整まで検討できておらず、オンデマンドモードで動かしながら探っていく方針となりました。
そのため、DynamoDBのマイグレーション時にオンデマンドモードで作成したいと思ったのですが、よく見かけるサンプルでは`プロビジョンド`になってしまいました。
そのため、個人的な興味もあって、オンデマンドモードで作成するにはどうすればいいかを調べました。

:::note info
尚、以下にも記載されていますが、キャパシティモードはマイグレーションよりAWSコンソールで調整する、でいいと思います。
ただ、今回は初回作成時にオンデマンドモードで作成するにはどうしたらいいか興味もあって調べてみました。

[マイグレーションは RDBMS と区別しない](https://tech.willgate.co.jp/entry/2018/02/28/134537#%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF-RDBMS-%E3%81%A8%E5%8C%BA%E5%88%A5%E3%81%97%E3%81%AA%E3%81%84)
> コード中のコメントにも記載したとおり、キャパシティユニット（以下、CU）に関しては、テーブル作成時は仮の値（最小の 5 とか）を入れておき、あとから管理コンソール上で値を更新するようにしています。
> CU は環境（本番／ステージングなど）によって変わるうえに、運用の中で変化していく値でもあるため、マイグレーションで管理する必要性が薄いことが理由です。
:::



## 結論

以下でオンデマンドモードでテーブル作成できました。

```diff_php
    public function up()
    {
        // テスト時には DynamoDB を利用しない
        if (app()->environment('testing')) {
            return;
        }

        $params = [
            'TableName' => $this->getTableName('Movies'),
            'KeySchema' => [
                [
                    'AttributeName' => 'year',
                    'KeyType' => 'HASH',
                ],
                [
                    'AttributeName' => 'title',
                    'KeyType' => 'RANGE',
                ],
            ],
            'AttributeDefinitions' => [
                [
                    'AttributeName' => 'year',
                    'AttributeType' => 'N'
                ],
                [
                    'AttributeName' => 'title',
                    'AttributeType' => 'S'
                ],
            ],
-           'ProvisionedThroughput' => [
-               'ReadCapacityUnits' => 5,
-               'WriteCapacityUnits' => 5,
-           ],
+           // キャパシティモード: オンデマンド
+           "BillingMode" => "PAY_PER_REQUEST",
        ];

        resolve(DynamoDbClientService::class)->getClient()->createTable($params);
    }
```

## 調べた経緯

AWSコンソールでオンデマンドモードにしたテーブルのテーブル定義を AWS CLI で確認してみます。

```sh
$ aws dynamodb describe-table --table-name=develop_comments 
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "comment_id",
                "AttributeType": "S"
            },
            # ...
        ],
        "TableName": "develop_comments",
        "KeySchema": [
            {
                "AttributeName": "comment_id",
                "KeyType": "HASH"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2022-08-01T20:11:45.341000+09:00",
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 0, # ★
            "WriteCapacityUnits": 0 # ★
        },

# (以降省略)
```

なので、単純にキャパシティユニットを`0`にすればよさそうですが、実行してみるとエラーになってしまいます。

```sh
$ aws dynamodb update-table \
    --table-name develop_comments \
    --provisioned-throughput ReadCapacityUnits=0,WriteCapacityUnits=0


Parameter validation failed:
Invalid value for parameter ProvisionedThroughput.ReadCapacityUnits, value: 0, valid min value: 1
Invalid value for parameter ProvisionedThroughput.WriteCapacityUnits, value: 0, valid min value: 1
```

次に AWS CLI のリファレンスをよく読んでみます。その中で、

https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html

- `Example 2: To create a table in On-Demand Mode`

```sh
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST"
        }
```
というのが記載されているので、これを参考に試していたらうまくいきました。。。

## 参考資料
https://tech.willgate.co.jp/entry/2018/02/28/134537


## さいごに
運動通信社は
「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、
一緒に働く仲間を募集しています！

https://sportsbull.jp/about/#recruit