AWS AppSync リゾルバ (VTL) の書き方サンプル No.8 – Amazon DynamoDB 応用編 2つのクエリをアトミックに実行

こんにちは、広野です。

AWS AppSync を使用したアプリケーションを開発する機会があり、リゾルバ、主に VTL の書き方に関してまとまった知識が得られたので紹介します。前回からの続きもので、今回は 1つの VTL で 2つのクエリをアトミックに (同期的に冪等性を担保して) 実行する方法を紹介します。

本記事では、VTL の書き方にフォーカスしています。ご了承ください。
AWS AppSync、リゾルバ、VTL の説明については以下の記事をご覧下さい。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.1 - Amazon DynamoDB GetItem
Amazon DynamoDB に VTL で GetItem をかけるときの基本的な書き方を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.2 – Amazon DynamoDB BatchGetItem
Amazon DynamoDB に VTL で BatchGetItem をかけるときの基本的な書き方を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.3 – Amazon DynamoDB Query
Amazon DynamoDB に VTL で Query をかけるときの基本的な書き方を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.4 - Amazon DynamoDB PutItem
Amazon DynamoDB に VTL で PutItem をかけるときの基本的な書き方を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.5 – Amazon DynamoDB UpdateItem
Amazon DynamoDB に VTL で UpdateItem をかけるときの基本的な書き方を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.6 - Amazon DynamoDB 応用編 引数内のフラグにより処理を分ける
Amazon DynamoDB に VTL でデータ読み書きをさせるときに、引数内のフラグにより実行させる処理を分岐する方法を紹介します。
AWS AppSync リゾルバ (VTL) の書き方サンプル No.7 - Amazon DynamoDB 応用編 2つのクエリを直列に実行
Amazon DynamoDB に VTL で 複数のクエリを直列に実行するときの書き方を紹介します。前のクエリの結果を後のクエリで使用することができるスグレモノです。
AWS AppSync を使って React アプリからキックした非同期ジョブの結果をプッシュ通知で受け取る
非同期ジョブを実行した後、結果をどう受け取るか?というのは開発者として作り込み甲斐のあるテーマです。今回は React アプリが非同期ジョブを実行した後に、AWS AppSync 経由でジョブ完了のプッシュ通知を受け取る仕組みを紹介します。

やりたいこと

以下のような処理をしたいです。冒頭、アトミックにという表現をしましたが、言葉を変えて説明します。

  • アプリからの1回のリクエストを受けて、リゾルバの中で 2つの書き込みオペレーションを実行したい。
  • ただし、2つのオペレーションが両方とも成功した場合にのみ、オペレーションをコミットしたい。もし片方が失敗した場合は、成功した方もオペレーションを無効にしたい。

これは、以下のように Amazon DynamoDB が提供している TransactWriteItems API を利用することで実現できます。

公式には、以下のドキュメントをご覧下さい。

本記事のサンプルでは、アプリから AWS AppSync に「2つの書き込みオペレーション」リクエストを受けたとします。テーブル名はリゾルバの別の設定 (Data Source) で設定しますが、実際に使用されるのはリクエストマッピングテンプレート内で設定されたテーブルになります。

  • 1つ目のオペレーション: パーティションキー pkey、ソートキー skey1、属性 attr1 をテーブル A に書き込み
  • 2つ目のオペレーション: パーティションキー pkey、ソートキー skey2、属性 attr2 をテーブル B に書き込み

Amazon DynamoDB に TransactWriteItems する VTL

リクエストマッピングテンプレート

{
  "version": "2018-05-29",
  "operation": "TransactWriteItems",
  "transactItems": [
    ## 1つ目のオペレーションを定義
    {
      "table": "TableA",
      "operation": "PutItem",
      "key": {
        "pkey": $util.dynamodb.toDynamoDBJson($context.arguments.pkey),
        "skey1": $util.dynamodb.toDynamoDBJson($context.arguments.skey1)
      },
      "attributeValues": {
        "attr1": $util.dynamodb.toDynamoDBJson($context.arguments.attr1)
      }
    },
    ## 2つ目のオペレーションを定義
    {
      "table": "TableB",
      "operation": "PutItem",
      "key": {
        "pkey": $util.dynamodb.toDynamoDBJson($context.arguments.pkey),
        "skey2": $util.dynamodb.toDynamoDBJson($context.arguments.skey2)
      },
      "attributeValues": {
        "attr2": $util.dynamodb.toDynamoDBJson($context.arguments.attr2)
      }
    }
  ]
}

transactItems の中に、配列で同期的に実行したいオペレーション、ここでは 2つの PutItem を定義しています。

関数 1 のレスポンスマッピングテンプレート

この例では、エラーになったときは “error” を返すようにしています。

#if($ctx.error)
  $util.toJson({
    "pkey": "error"
  })
#elseif($ctx.result)
  $util.toJson({
    "pkey": $context.arguments.pkey
  })
#else
  $util.toJson({
    "pkey": "error"
  })
#end

まとめ

いかがでしたでしょうか。

複数のオペレーション結果を総合的に判断させるクエリが作成が必要なケースはあると思います。もっとエラー時のレスポンスはきちんと作らないといけないとは思いますが。

本記事が皆様のお役に立てれば幸いです。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもフロントエンド開発の方が好きでして、バックエンド構築を簡単にしてくれたAWSには感謝の気持ちの方が強いです。
取得資格:AWS 認定は13資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2024 Japan AWS Top Engineer 受賞
2022 - 2024 AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする
クラウドに強いによるエンジニアブログです。
SCSKは専門性と豊富な実績を活かしたクラウドサービス USiZE(ユーサイズ)を提供しています。
USiZEサービスサイトでは、お客様のDX推進をワンストップで支援するサービスの詳細や導入事例を紹介しています。
AWSアプリケーション開発クラウドソリューション
シェアする
タイトルとURLをコピーしました