Question

in my google app application, whenever a user purchases a number of contracts, these events are executed (simplified for clarity):

  • user.cash is decreased
  • user.contracts is increased by the number
  • contracts.current_price is updated.
  • market.no_of_transactions is increased by 1.

in a rdms, these would be placed within the same transaction. I conceive that google datastore does not allow entities of more than one model to be in the same transaction.

what is the correct approach to this issue? how can I ensure that if a write fails, all preceding writes are rolled back?

edit: I have obviously missed entity groups. Now I'd appreciate some further information regarding how they are used. Another point to clarify is google says "Only use entity groups when they are needed for transactions. For other relationships between entities, use ReferenceProperty properties and Key values, which can be used in queries". does it mean I have to define both a reference property (since I need queriying them) and a parent-child relationship (for transactions)?

edit 2: and finally, how do I define two parents for an entity if the entity is being created to establish an n-to-n relationship between 2 parents?

Was it helpful?

Solution

After a through research, I have found that a distributed transaction layer that provides a solution to the single entity group restriction has been developed in userland with the help of some google people. But so far, it is not released and is only available in java.

OTHER TIPS

Let me add a quote from the Datastore documentation:

A good rule of thumb for entity groups is that they should be about the size of a single user's worth of data or smaller.

You could create a pseudo root entity and put everything below this. Then, you execute everything in a transaction.

shanyu, you mentioned the distributed transaction layer that lets you operate across arbitrarily many entity groups in a single transaction. it actually has been released, it just hasn't been advertised very loudly. it was designed and written by daniel wilkerson and erick armbrust, with some consulting on my part. dan describes it in this talk.

nick johnson has also described how to do "transfer" type operations across entity groups, similar to what you describe. it's not as general purpose as tapioca-orm, but it's simpler and lighter weight.

there's a related built in feature, transactional tasks, that lets you add a task to a queue within a datastore transaction, such that it will only be added if the transaction commits successfully. that task can then do more datastore operations, including a transaction on a different entity group. it's not as strong as dan and erick's solution, but it does give you guaranteed eventual consistency across entity groups, which is good enough for many use cases, without the extra overhead.

in response to your questions: 1) you're not required to use both reference properties and parent/child relationships (ie entity groups). that guideline just means that entity groups limit datastore write throughput, since writes are serialized per entity group. you should be aware of that if you're considering structuring your data into entity groups just for ancestor queries.

2) an entity can't have more than one parent. if you want to model a many-to-many relationship, you should generally use a ListProperty of reference properties (ie keys). see this article and this talk for details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top