既然您的表中已有游戏项目,现在可以学习如何模拟游戏玩家在进行中的游戏中执行操作。
此操作有两种处理方式。在第一种方式中,您使用 GetItem API 检索项目。然后,根据游戏玩家的操作更新应用程序中的游戏项目。最后,使用 PutItem API 替换 DynamoDB 中的现有项目。虽然此方式奏效,但它需要向 DynamoDB 表发出多个请求,并且可能会覆盖在获取和重写游戏项目之间发生的任何更改。
此操作的第二种处理方式是在 DynamoDB 中使用 UpdateItem API 调用。借助 UpdateItem API,您可以通过单一请求更新适当的 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 开发工具包并创建 DynamoDB 文档客户端实例。
然后,定义名为 performMove 的方法。此方法类似于用户请求进行操作时在应用程序中使用的内部方法。该脚本会整合 UpdateItem API 调用的参数。首先,它会更改游戏中的两个属性,即执行操作的最后一名用户和更改堆中的元素数量。
然后,UpdateItem API 参数会对游戏的当前状态进行一些断言。在更新项目之前,ConditionExpression 会被评估,以确认项目处于您希望的状态。您在条件表达式中做出以下三个断言:
- 请求执行某操作的用户是游戏中的两名用户之一;
- 当前回合属于请求执行该操作的用户;
- 所更改的堆的当前值高于更改目标值。
最后,参数声明 ALL_NEW 的 ReturnValue ,也就是说,DynamoDB 会在其值更新之后返回整个项目。此时,您的应用程序可以评估游戏,看看是否有获胜者。
文件底部举例说明了应用程序如何调用此方法。您可以使用以下命令执行脚本:
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
您的条件请求这次失败了。请求用户 (theseconduser) 是最近要操作的用户。另外,更改堆 (heap1) 已有值 3,这意味着用户没有更改任何内容。正因如此,请求遭据。