App Engine, transacciones e idempotency

Por favor ayúdame a encontrar mi malentendido.

Estoy escribiendo un juego de rol en App Engine. Ciertas acciones que el jugador toma consumen cierta estadística. Si la estadística llega a cero, el jugador no puede realizar más acciones. Sin embargo, empecé a preocuparme por engañar a los jugadores. ¿Qué sucede si un jugador envía dos acciones muy rápidamente, una al lado de la otra? Si el código que disminuye la estadística no está en una transacción, entonces el jugador tiene la posibilidad de realizar la acción dos veces. Entonces, debería envolver el código que disminuye la estadística en una transacción, ¿verdad? Hasta ahora tan bueno.

En GAE Python, sin embargo, tenemos esto en eldocumentación:

Nota: Si su aplicación recibe una excepción al enviar una transacción, no siempre significa que la transacción haya fallado. Puede recibir excepciones de Timeout, TransactionFailedError o InternalError en los casos en que las transacciones se hayan confirmado y finalmente se apliquen correctamente. Siempre que sea posible, haga que sus transacciones del almacén de datos sean idempotentes para que, si repite una transacción, el resultado final sea el mismo.

Whoops. Eso significa que la función que estaba ejecutando se parece a esto:

<code>
def decrement(player_key, value=5):
  player = Player.get(player_key)
  player.stat -= value
  player.put()
</code>

Bueno, eso no va a funcionar porque la cosa no es idempotente, ¿verdad? Si pongo un bucle de reintento a su alrededor (¿necesito hacerlo en Python? He leído que no necesito hacerlo en SO ... pero no puedo encontrarlo en la documentación) podría aumentar el valor dos veces, ¿Correcto? Dado que mi código puede detectar una excepción, el almacén de datos aún confirmó los datos ... ¿eh? ¿Cómo puedo solucionar esto? Es este un caso donde necesitotransacciones distribuidas? ¿De verdad?

Respuestas a la pregunta(4)

Su respuesta a la pregunta