How to correctly compose a game "Buy / Sell Item" transaction

Viewed 64

I am working on a "Buy/Sell Item" functionality for an rpg game. If I am correct following actions need to happen in a single transaction

  1. Get player based on playerID from "Players" table
  2. Check if player has enough gold, if so create new item object
  3. Write new item object to "Items" table, where owner is based on pllayerID
  4. Update "Players" table row where owner is playerID, deduct gold based on item cost

If in above players gold changes while transaction is running or step 3 or 4 fail to execute simultaneously transaction should fail.

I've read the docs and can see that DynamoDB has TransactWriteItems and TransactGetItems which seem to be perfect for this, but are separate. Can I somehow use them in a single transaction?

1 Answers

Once you have your playerID, you should be able to merge step 4 into step 2 and then do steps 2-3 within one TransactWriteItems:

  1. UPDATE the value of the gold conditionally - if enough gold is present, deduct the item cost immediately, else condition fails, and so does TransactWriteItems.
  2. If you made it here, there was enough gold, and you can create and write the new object to the Items table.

Edit for explanation as to why this works:

TransactWriteItems groups the actions "Update gold" and "put item" as a single all-or-nothing operation: either they both succeed or they both fail. And if another operation interferes, they also both fail (no race condition).

For example:

  • If there is not enough gold, the update fails, so the add item also fails.
  • If adding the item fails, the changes made to the gold will not be kept (the update will "fail")
  • If another operation is modifying the gold amount, both fail.

Essentially, it is impossible to either:

  1. subtract the gold, but not add the item
  2. add the item but not subtract the gold

Because they are both within the TransactWriteItems operation, either both happen, or neither does.

You can find an example in Java here. (For your use case, you can simply drop the customer validation and change "product status update" to "player gold update" and "add order" to "add item".)

For more details, see TransactWriteItems documentation here.

Related