Giờ đây, khi đã có một mục trò chơi trong bảng, bạn có thể tìm hiểu cách mô phỏng nước đi của người chơi cho một trò chơi đang diễn ra.
Bạn có thể xử lý thao tác này theo hai cách. Cách thứ nhất là bạn truy xuất mục bằng API GetItem. Sau đó, bạn cập nhật mục trò chơi trong ứng dụng của mình theo nước đi của người chơi. Cuối cùng, bạn thay thế mục hiện có trong DynamoDB bằng API PutItem. Tùy chọn này hiệu quả nhưng đòi hỏi nhiều yêu cầu đối với bảng DynamoDB của bạn và có nguy cơ ghi đè mọi thay đổi xảy ra trong quá trình tải và ghi lại mục trò chơi.
Cách thứ hai để xử lý thao tác này là sử dụng lệnh gọi API UpdateItem trong DynamoDB. Với API UpdateItem, bạn có thể cập nhật mục DynamoDB của mình tại chỗ thông qua một yêu cầu. Bạn chỉ định mục mình muốn thay đổi, các thuộc tính cần thay đổi và mọi điều kiện bạn muốn xác nhận trên mục đó. Đây là cách nên dùng để thực hiện thay đổi đối với mục vì cách này không yêu cầu nhiều lệnh gọi đến cơ sở dữ liệu của bạn.
Trong thư mục scripts/, có một tệp mang tên performMove.js chứa nội dung như sau:
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 })
Tập lệnh này hơi phức tạp nên hãy tiến hành từng bước một.
Giống như tập lệnh trước, bạn nhập AWS SDK và tạo phiên bản Máy khách tài liệu DynamoDB.
Sau đó, bạn xác định một phương pháp có tên performMove. Phương pháp này tương tự như một phương pháp nội bộ sẽ được dùng trong ứng dụng của bạn khi người dùng yêu cầu thực hiện nước đi. Tập lệnh sẽ tập hợp các tham số cho lệnh gọi API UpdateItem. Trước tiên, tập lệnh thay đổi hai thuộc tính trong trò chơi -- người dùng cuối cùng thực hiện nước đi và số lượng thành phần trong đống đã thay đổi.
Sau đó, các tham số API UpdateItem đưa ra một số xác nhận về trạng thái hiện tại của trò chơi. ConditionExpression được đánh giá trước khi cập nhật mục để xác nhận rằng mục đó đang ở trạng thái bạn muốn. Bạn đang xác nhận ba điều sau trong biểu thức điều kiện của mình:
- Người dùng yêu cầu thực hiện nước đi là một trong hai người dùng trong trò chơi;
- Lượt hiện tại thuộc về người dùng yêu cầu thực hiện nước đi;
- Giá trị hiện tại của đống được thay đổi cao hơn giá trị sau khi thay đổi.
Cuối cùng, các tham số xác định ReturnValue của ALL_NEW, nghĩa là DynamoDB trả về toàn bộ mục sau khi cập nhật giá trị. Sau khi có thông tin này, ứng dụng của bạn có thể đánh giá trò chơi để xem có người thắng hay không.
Ở cuối tệp có một ví dụ về cách gọi phương pháp này trong ứng dụng của bạn. Bạn có thể thực thi tập lệnh bằng lệnh sau:
Bạn sẽ thấy kết quả đầu ra như sau trong terminal của mình:
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
Bạn có thể thấy tác vụ ghi đã thành công và trò chơi đã được cập nhật.
Hãy thử chạy lại tập lệnh trong terminal của bạn. Bạn sẽ thấy kết quả đầu ra như sau:
Yêu cầu có điều kiện của bạn lần này không thành công. Người dùng yêu cầu -- theseconduser -- là người chơi đã thực hiện nước đi gần nhất. Ngoài ra, đống được thay đổi -- heap1 -- đã có giá trị là 3, nghĩa là người dùng không hề thay đổi gì. Do đó, yêu cầu đã bị từ chối.