I need a safe procedure for modifying two datastore keys. The problem is, this can’t be done in a single API call, so it can fail half-way, causing data loss or duplication.
It is possible to do this safely using mutex locks, but this means many calls to UpdateAsync
, which might be a burden on the request budget. I want to find the fewest calls necessary to be able to securely complete a transaction.
My first concept requires 6 UpdateAsync
calls. The intent is for the transaction to be able to be resumed at any point in-between these calls, so imagine the server shuts down and a player has to rejoin in-between each request.
- The first 2 calls establish a lock on each key, which lives in the
DataStoreKeyInfo
metadata and contains some metadata of its own to store details about the transaction and its state.- If an outage occurs here, then when a player joins and their data is locked, it resumes the transaction by requesting to lock the other key.
- Once both keys are locked, the data needs to be validated to ensure the transaction is legal. If it passes, 2 more
UpdateAsync
calls update the data and change the metadata to indicate the transaction is partially complete. If it doesn’t pass then the data isn’t changed and the metadata indicates that the transaction failed.- If the transaction is resumed here where only 1 key is partially complete/failed and the other is still locked then it updates the other.
- A key can be unlocked when it is partially complete/failed if the other is also partially complete/failed or is no longer locked. The lock has to uniquely identify transactions so that it doesn’t get confused if the other key is locked again but as part of a different transaction.
in other terms:
- lock player 1’s data
- lock player 2’s data
- update player 1’s data once both are locked, mark as partially complete/failed
- update player 2’s data once both are locked, mark as partially complete/failed
- unlock player 1’s data once player 2’s data is marked/unlocked
- unlock player 2’s data once player 1’s data is marked/unlocked
Is there another solution which uses less of the request budget? Ideally some day there will be a built-in feature to modify multiple datastore keys in unison as a single API call, but until then, some version of this is needed.