Reputation: 91
We are developing an IOS game and are using google-app-engine for backend. The users can cash in in-game money by tapping buildings. The users tap several buildings fairly fast and this causes several concurrent transactions on the same object (USER) and on different buildings.
Unfortunately this means that the 4-5th tap times-out since it looses retries. It also means that 2nd to 5th tap is very slow due to the lock.
My first thought was to make the transaction into a task, but then totalAmount will be wrong on the second call to the function, since the first call is not completed yet.
So any good ways to support multiple fast updates to the same entity?
int retries = 5;
while (retries > 0) {
// Wrap everything into a transaction from here
TransactionOptions options = TransactionOptions.Builder.withXG(true);
Transaction txn = datastore.beginTransaction(options);
try{
// Ok we got the template - now check against the
// Update user... with money gained
// Update Building...money withdrawn
//Do the transaction
datastore.put(txn, user.getEntity());
datastore.put(txn, building.getEntity());
txn.commit();
// do callback code...which returns TotalMoney
break;
} catch (Exception e) {
if(retries > 0){
retries--;
}
else{
//fail code...
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
Upvotes: 0
Views: 311
Reputation: 2240
One possibility is to NOT use XG transactions, or transactions at all. Instead, it will be far more beneficial to have a transaction log, where you log all actions. That way, you can have a task or backend apply the effets of the transaction log such that if things fail, they will eventually become consistent. This will greatly improve your front-end throughput, and it will make customer service much easier in the long term.
One thing to remember is the general rule of thumb about updates to an entity group: design your entity groups such that you update them at a rate of 1/s. The actual rate is much higher, but this is a good rule to prevent collisions and contention.
Upvotes: 1
Reputation: 80340
For consistency you need transactions, for responsiveness you shoul use backends:
Use backend instance to keep data in memory for fast update.
Whenever data is updated in backend also start a task and transactionally update entity in Datastore.
Upvotes: 3