Micro
Micro

Reputation: 10891

Save entity to Datastore and return it so that any further queries to the same entity are guaranteed to reflect the new updates

I want to load an entity by key, update it, save it back to Datastore and then return it to the client from an endpoint. However, I want to make absolutely sure that when I return the entity to the client, the updated entity has been saved and propagated across the datastore. This way, if the client queries for that entity with another endpoint immediately after, the updated one will return.

Using Objectify, this is what I have so far:

First I load the entity, update some values and then load it again by the entity key and return it. Will this second load and return of the entity be strongly consistent and reflect the new value?

// Load the entity by key
Key<Thing> thingKey = Key.create(Thing.class, id);
Thing thing = ofy().load().key(thingKey).now();

// Update some values
thing.setSomeProperty("new value");

// Save entity
ofy().save().entity(thing);

// Load entity by key - will this loaded entity be guaranteed to reflect the above update?
return ofy().load().key(thingKey).now();

Note: I do not want to return the local entity I set the new values to because I do not want the client to potentially query for the entity with the new updates and not get it because they haven't been committed yet due to eventual consistency.

Could this below be another option to achieve the same effect?

// Load the entity by key
Key<Thing> thingKey = Key.create(Thing.class, id);
Thing thing = ofy().load().key(thingKey).now();

// Update some values
thing.setSomeProperty("new value");

// Will this save wait until the entity is saved/propagated across the datastore and thus any queries to this entity after this statement will reflect the new update?
ofy().save().entity(thing).now();

// Just return the entity we updated
return thing

Upvotes: 0

Views: 298

Answers (1)

stickfigure
stickfigure

Reputation: 13556

There is no difference between those two sequences. The last load() simply loads the same object out of the session cache. You might as well just return the object.

Keep in mind that you need to run this inside a transaction to be safe. Otherwise you run the risk that some other conflicting write will get overwritten and therefore lost between the load and the save.

return ofy().transact(() -> {
    Key<Thing> thingKey = Key.create(Thing.class, id);
    Thing thing = ofy().load().key(thingKey).now();

    thing.setSomeProperty("new value");

    ofy().save().entity(thing).now();

    return thing;
}

BTW with Firestore, eventual consistency really isn't a thing anymore. But that doesn't mean that data won't necessarily be stale. Technically any piece of data can be stale the moment after it is fetched from the datastore. A transaction ensures a consistent view of the data (ie, all transactions are serializable so data will not be lost).

Upvotes: 2

Related Questions