RCB
RCB

Reputation: 2263

Objectify transaction vs. regular load then save

I need only confirmation that I get this right. If, for example I have an Entity X with a field x, and when a request is sent I want to do X.x++. If I use just X = ofy().load().type(X.class).id(xId).get() then I do some calculations and afterwards I do X.x++ and the I save it. If during the calculations another request is posted, I'll get an unwanted behavior. And instead if I'll do this all in a transaction, the second request won't have access to X until I finish.

Is it so?

Sorry if the question is a bit nooby.

Thanks, Dan

Upvotes: 1

Views: 967

Answers (2)

Jimmy Kane
Jimmy Kane

Reputation: 16825

Yes you got it right but when using transaction remember the first that completes wins and the rest fail. Look also at @Peter Knego's answer for how they work.

But don't worry about the second request if it fails to read. You have like 2 options:

  1. Force a retries
  2. Use eventual consistency in your transactions

As far as the retries are concerned:

Your transaction function can be called multiple times safely without undesirable side effects. If this is not possible, you can set retries=0, but know that the transaction will fail on the first incident of contention

Example:

@db.transactional(retries=10)

As far as eventual consistency is concerned:

You can opt out of this protection by specifying a read policy that requests eventual consistency. With an eventually consistent read of an entity, your app gets the current known state of the entity being read, regardless of whether there are still committed changes to be applied. With an eventually consistent ancestor query, the indexes used for the query are consistent with the time the indexes are read from disk. In other words, an eventual consistency read policy causes gets and queries to behave as if they are not a part of the current transaction. This may be faster in some cases, since the operations do not have to wait for committed changes to be written before returning a result.

Example:

@db.transactional()
def test():
    game_version = db.get(
        db.Key.from_path('GameVersion', 1),
        read_policy=db.EVENTUAL_CONSISTENCY)

Upvotes: 2

Peter Knego
Peter Knego

Reputation: 80330

No, GAE transaction do not do locking, they use optimistic concurrency control. You will have access to X all the time, but when you try to save it in the second transactions it will fail with ConcurrentModificationException.

Upvotes: 2

Related Questions