テーブルにゲームアイテムができたので、進行中のゲームで行動しているプレイヤーをシミュレートする方法を学習できます。
この操作を処理できる方法は 2 つあります。最初の方法では、GetItem API を使用してアイテムを取得します。次に、プレイヤーが実行した行動に応じて、アプリケーションのゲームアイテムを更新します。最後に、PutItem API を使用して DynamoDB の既存のアイテムを置き換えます。このオプションは機能しますが、DynamoDB テーブルへの複数のリクエストが必要で、ゲームアイテムの取得と再書き込みの間に発生した変更を上書きしてしまうリスクがあります。
この操作を処理する 2 番目の方法は、DynamoDB で UpdateItem API 呼び出しを使用することです。UpdateItem API を使用すると、1 回のリクエストで所定の場所にある DynamoDB アイテムを更新できます。変更するアイテム、変更する属性、およびアイテムにアサートする条件を指定します。これは、データベースへの複数の呼び出しを必要としないため、アイテムに変更を加えるための好ましい方法です。
scripts/ ディレクトリには、performMove.js というファイルがあり、次の内容が含まれています。
const AWS = require('aws-sdk')
const documentClient = new AWS.DynamoDB.DocumentClient()
const performMove = async ({ gameId, user, changedHeap, changedHeapValue }) => {
if (changedHeapValue < 0 ) {
throw new Error('Cannot set heap value below 0')
}
const params = {
TableName: 'turn-based-game',
Key: {
gameId: gameId
},
UpdateExpression: `SET lastMoveBy = :user, ${changedHeap} = :changedHeapValue`,
ConditionExpression: `(user1 = :user OR user2 = :user) AND lastMoveBy <> :user AND ${changedHeap} > :changedHeapValue`,
ExpressionAttributeValues: {
':user': user,
':changedHeapValue': changedHeapValue,
},
ReturnValues: 'ALL_NEW'
}
try {
const resp = await documentClient.update(params).promise()
console.log('Updated game: ', resp.Attributes)
} catch (error) {
console.log('Error updating item: ', error.message)
}
}
performMove({ gameId: '5b5ee7d8', user: 'theseconduser', changedHeap: 'heap1', changedHeapValue: 3 })
このスクリプトは少し複雑なので、ステップごとに見ていきましょう。
前のスクリプトと同様に、AWS SDK をインポートし、DynamoDB Document Client インスタンスを作成します。
次に、performMove というメソッドを定義します。このメソッドは、ユーザーが行動を行うことをリクエストしたときにアプリケーションで使用する内部メソッドに似ています。このスクリプトは、UpdateItem API 呼び出しのパラメータを組み立てます。まず、ゲームの 2 つの属性を変更します。その 2 つは、最後に移動したユーザーと、変更されたヒープ内の要素の数です。
UpdateItem API パラメータは、ゲームの現在の状態についていくつかのアサーションを作成します。ConditionExpression は、アイテムが更新される前に評価され、アイテムが目的の状態にあることを確認します。条件式で次の 3 つのアサーションを作成しています。
- 行動の実行をリクエストしているユーザーがゲーム内の 2 人のユーザーのうちの 1 人であること。
- 現在の順番は、行動の実行をリクエストしているユーザーのものであること。
- 変更されるヒープの現在の値が、変更される値よりも高いこと。
最後に、パラメータは ALL_NEW の ReturnValue を示します。これは、値が更新された後に DynamoDB がアイテム全体を返すことを意味します。これを取得したら、アプリケーションでゲームを評価して、勝者がいるかどうかを確認できます。
ファイルの下部に、このメソッドがアプリケーションでどのように呼び出されるかの例があります。次のコマンドでスクリプトを実行できます。
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
書き込みが成功し、ゲームが更新されたことがわかります。
ターミナルでスクリプトを再度実行してください。次の出力が表示されます。
今回は条件付きリクエストが失敗しました。リクエスト元のユーザー (theseconduser) が、最後に行動したプレイヤーでした。さらに、変更されたヒープ (heap1) の値はすでに 3 でした。これは、ユーザーが何も変更しなかったことを意味します。このため、リクエストは拒否されました。