LambdaでDynamoDBのトランザクション処理を行う

DynamoDBにトランザクションが追加されたようなのでLambdaで実行してみます。
今回のコードはeventから受け取ったデータを元にusersテーブルとuser_possessionsテーブルに同時にデータを挿入するという簡単なコードとなっています。

#実行環境#
- ランタイム：　Nodejs 8.0
- リージョン：　ap-northeast-1

#インラインで実行#

Lambdaにインラインでコードを書いて実行を試みます。

```index.js
'use strict';

const AWS = require('aws-sdk');
AWS.config.update({ region: 'ap-northeast-1'});
const documentClient = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
  let result;
  const lineId = event.line_id;
  const name = event.name;
  const params = {
    TransactItems: [{
      Put: {
        TableName : 'users',
        Item: {
          "line_id": lineId,
          "name": name,
        },
      },
    }, {
      Put: {
        TableName : 'user_possessions',
        Item: {
          "line_id":lineId,
          "total_token_amount": 0,
          "term_token_amount": 0,
        },
      },
    }]
  };
  //transactWriteメソッドで複数テーブルを更新
  await documentClient.transactWrite(params, (error, data) => {
    if(error){
      result = {
        statusCode: 500,
        head: "Unable to add item, Error JSON:",
      };
    }else{
      result = {
        statusCode: 201,
        head: "Successfully appended new user record",
      };
    }
  }).promise();
  return result;
};
```

```json:実行結果.
{
  "errorMessage": "documentClient.transactWrite is not a function",
  "errorType": "TypeError",
  "stackTrace": [
    "exports.handler (/var/task/index.js:32:24)"
  ]
}
```

むむ、サポートされたはずのtransactWriteメソッドが使えません。

##原因##

すかさず「documentClient.transactWrite is not a function」をググってみると、いい感じにgithubのページが出てきました。
https://github.com/aws/aws-sdk-js/issues/2392

"DynamoDB API was recently updated with added support for transactions and those operations were made available in the SDK in version [2.365.0](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md#23650)."


トランザクションが使えるのは2.365以上とあります。どうやらSDKバージョンに問題があるようです。


改めてLambdaの実行環境を参照すると、AWS SDK for JavaScriptのバージョンが2.290.0となっています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html

これで問題が明らかになりました。
インラインで利用できるAWS SDKのバージョンが最新でないため、transactWriteメソッドが使えなかったようです。

そこで、下記の情報を参考にしながらデプロイパッケージを作成します。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-create-deployment-pkg.html


##デプロイパッケージを作成・アップロードして実行##

###1. ローカルでディレクトリを作成し、実行したいコードを置いておきます。
略。

###2. 次に、作成したディレクトリ内でaws-sdkをインストールします。

※ バージョンを指定しなくても最新のSDKがインストールされます。実行結果の下から三行のように出ていれば成功のようです。

```console:ターミナル.
$ npm install aws-sdk
```

```console:実行結果.
npm WARN saveError ENOENT: no such file or directory, open '/Users/taruya/projects/nmc/test/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/Users/taruya/projects/nmc/test/package.json'
npm WARN test No description
npm WARN test No repository field.
npm WARN test No README data
npm WARN test No license field.

+ aws-sdk@2.405.0
added 14 packages from 66 contributors and audited 17 packages in 2.098s
found 0 vulnerabilities
```

###3. zipでまとめる。
zipを行うディレクトリ内のルートで以下のコマンドを入力します。
※対象ファイルを「.」としていますが、ディレクトリ外で作業を行う場合は直接ファイル名を入力してください。

```console:ターミナル.
$ zip -r ../ディレクトリ名.zip .
```

###4. Lambdaにアップロードして再び実行

コマンドラインを使う方法もあるのでしょうが、自分はAWS初学者なのでマネジメントコンソールの画面からzipファイルを直接アップロードしました。

```json:実行結果.
{
  "statusCode": 201,
  "head": "Successfully appended new user record"
}
```
成功！

##所感
AWSはドキュメントがしっかりしているので、エラーハンドリングがやりやすくてGood。

#Ref.
[速報]待望のDynamoDBのトランザクションがリリースされました！ #reinvent
https://dev.classmethod.jp/cloud/aws/new-release-dynamodb-transactions/

Node.js の Lambda デプロイパッケージを作成するには、どうすればよいですか？
https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-deployment-package-nodejs/

Class: AWS.DynamoDB.DocumentClient
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html