이제 게임 항목이 테이블이 포함되었으니 진행 중인 게임에서 동작 중인 플레이어를 시뮬레이션하는 방법을 알아볼 수 있습니다.
이 작업은 2가지 방법으로 처리될 수 있습니다. 첫 번째 방법에서는 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 SDK를 가져오고 DynamoDB Document Client 인스턴스를 생성합니다.
그런 다음 performMove라는 메서드를 정의합니다. 이 메서드는 사용자가 동작을 취하기 위한 요청을 제출할 때 애플리케이션에서 사용될 수 있는 내부 메서드와 유사합니다. 이 스크립트는 UpdateItem API 호출에 대한 파라미터를 어셈블링합니다. 먼저, 이 메서드는 게임의 2가지 속성, 즉 마지막으로 동작을 취한 사용자와 변경된 힙의 요소 수를 변경합니다.
그러면 UpdateItem API 파라미터가 게임의 현재 상태에 대한 일부 어설션을 수행합니다. 항목을 업데이트하기 전에 항목이 원하는 상태에 있는지 확인하기 위해 ConditionExpression이 다시 평가됩니다. 조건 식에서는 다음 3가지 어설션을 수행합니다.
- 동작의 수행을 요청하는 사용자는 게임 사용자 2명 중 1명입니다.
- 현재 턴은 동작 수행을 요청하는 사용자에게 속합니다.
- 변경되는 힙의 현재 값은 변경할 값보다 큽니다.
마지막으로, 파라미터는 ReturnValue를 ALL_NEW로 명시합니다. 이렇게 하면 값이 업데이트된 후 DynamoDB가 전체 항목을 반환합니다. 이 작업이 완료되면 애플리케이션에서 게임을 평가하여 승자가 있는지 여부를 확인할 수 있습니다.
파일의 맨 아래에 애플리케이션에서 이 메서드를 호출하는 방법에 대한 예제가 나와 있습니다. 다음 명령을 사용하여 스크립트를 실행할 수 있습니다.
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
쓰기 작업이 성공했고 게임이 업데이트되었음을 알 수 있습니다.
터미널에서 스크립트를 다시 실행합니다. 다음 출력이 표시됩니다.
이번에는 조건부 요청이 실패했습니다. 요청하는 사용자(-- theseconduser --)가 최근에 동작한 사용자였습니다. 또한 변경된 힙(-- heap1 --)의 값이 이미 3이므로 사용자가 변경한 것이 없습니다. 이로 인해 요청이 거부되었습니다.