10

Considérese el segundo ejemplo de "Usos de las transacciones" ("actualizar una entidad con una clave llamada, o cree que si todavía no existe"):GAE HDR: ¿Las recuperaciones de entidad por clave son consistentes dentro de una transacción XG?

https://developers.google.com/appengine/docs/java/datastore/transactions

Ahora considere este escenario. Un juego multijugador permite solo una partida entre dos jugadores. Para garantizar eso, se crea una clave usando cada una de las teclas del jugador. Esta clave se usa como la clave de una entidad UniqueMatch.

Para crear una coincidencia, se crea una transacción XG. Dentro de esta transacción:

  1. Comprobamos si ya no hay una entidad UniqueMatch con esa clave. Si una llamada a datastore.get() utilizando esa clave no arroja EntityNotFoundException, entonces sabemos que ya existe una coincidencia entre esos dos jugadores, por lo que deshacemos() y mostramos un mensaje de error a los jugadores.

  2. Colocamos() todas las entidades que necesitamos poner para crear una coincidencia. Esto incluye la entidad UniqueMatch, más algunas otras pocas entidades.

  3. La transacción se confirma.

Esto parece funcionar bien. Sin embargo, noté que puedo crear dos coincidencias entre dos jugadores en un período de tiempo corto. Por un período de tiempo pequeño (hasta 10-20s en una de las pruebas, en realidad), mis llamadas a datastore.get (clave) arrojan EntityNotFoundException a pesar de que esa clave ya se ha puesto().

Esto parece ser una consistencia eventual. ¿Pero no son las entidades de los resultados por la clave garantizados para ser fuertemente consistentes? ¿Esta garantía se ve afectada por el hecho de que esto se hace dentro de una transacción XG?

Gracias de antemano,

+0

esto puede ser un problema similar. Me equivoqué en los comentarios, ver el comentario de Guido. http://stackoverflow.com/questions/12367904/write-read-with-high-replication-datastore-ndb/12368444 También estaba seguro de que una vez que tuvieras una clave de un .put, siempre podrías recuperar el elemento, pero parece no ser el caso. Memcache tal vez. –

+0

Hmmm No estoy tan seguro de eso, Guido está hablando específicamente de consultas, no de recuperación de entidades por clave. Para las consultas, esperaría una consistencia eventual (que está documentada correctamente en realidad). Memcache puede ser una opción, sí. Si no encuentro una mejor manera, investigaré Memcache, gracias. – fnf

+0

seguro, mencionaste entidad por claves, así que pensé en vincular esa discusión. Rescindiré tu pregunta. –

Respuesta

1

Creo que el tema que se está viendo puede ser debido a que el almacén de datos se pone (por llave o consultas) sólo se ve el estado del almacén de datos en el inicio de la transacción.

Desde el docs (bajo aislamiento y consistencia):

En una transacción, todas las lecturas reflejar el estado actual, consistente del almacén de datos en el momento comenzó la transacción. Esto no incluye puts y eliminaciones previas dentro de la transacción. Las consultas y los accesos a una transacción están garantizados para ver una instantánea única y coherente del almacén de datos desde el comienzo de la transacción.

Además, fuera de la transacción, solo verá pone que se han cometido (docs):

Entidades recuperados del almacén de datos mediante consultas o se hace sólo verá los datos confirmados.

Una posible solución:

Crear la entidad UniqueMatch fuera de la transacción (appengine no permitirá que usted ponga una entidad con la misma clave, por lo que va a lanzar una excepción si la entidad con la misma clave ya existe). A continuación, puede crear/poner las otras entidades necesarias para crear una coincidencia dentro de una transacción (si es necesario).

Por último, asegúrese de que al crear la clave para la UniqueMatch clave que se crea siempre con los jugadores en el mismo orden, porque key(playerA,playerB)!=key(playerB,playerA)

Cuestiones relacionadas