Search code examples
google-app-enginegoogle-cloud-datastoreobjectify

Google Datastore - ancestor query doesn't appear to be strongly consistent if entity does not exist


Suppose you have a method like this:

Entity entity = ofy().load().type(Entity.class)
        .ancestor(key)
        .filter("someField", someValue)
        .first().now();

if (entity == null) {
    // Entity does not exist yet.
    // Write new entity to Datastore.
}

The method checks if a certain entity exists via an ancestor query. If it does not, it writes it to the datastore.

One thing I have found is that if the above method is executed twice at the exact same time, then two entities are written. It appears that entity is still seen as null due to a race condition.

I thought that ancestor queries are supposed to be strongly consistent and thus prevent the above scenario? It appears it is not strongly consistent when an entity does not exist.

Is there a way to prevent two entities from being written in the above case?


Solution

  • I could be wrong, but from the way you have worded the question, it sounds like you are confusing "strongly consistent" with "atomic". A strongly consistent read is guaranteed to reflect all updates that came before it, but is also stale the moment you execute it - someone else could have overwritten the data one microsecond later.

    The only way to prevent race conditions in the datastore is to use transactions. There is a fair amount of documentation on that online so I won't belabor it here.