Why would I ever want to load an Objectify entity asynchronously? And what does asynchronous loading actually mean?
According to Objectify documentation about loading,
Response from Google Cloud Support to support case 05483551:
“Asynchronous” in the context of Java means the use of “Futures” or Future-like constructs. A Future in java[1] is an object that represents an operation that doesn’t necessarily need to be performed and completed by the time the next line begins executing in the current thread.
A call to an asynchronous function in Java will return a Future immediately, representing the promise that a background “thread” will work on the computation/network call while the next line of the code continues to execute, not needing that result yet. When the method .get() is called on the Future object, either the result is returned, having been obtained in time, or the thread will wait until the result is obtained, passing execution to the next line after the .get() call only once this happens.
In Objectify, Futures were avoided, and instead the Result interface was defined[2], for reasons related to exceptions being thrown that made it painful to develop on the basis of Futures. They work in almost identical fashion, however. Where a regular Future has the method .get(), the Result interface (implemented by several different concrete classes depending what kind of Objectify call you’re doing) has .now(), which retrieves the result or waits the thread until it’s available.
The reason why you might want to load an entity asynchronously is when you have a request handler or API method that needs an Entity later in the function, but has some other computation to do as well, unrelated to the Entity. You can kick off the load for the entity in the first line, obtaining a Result, and then only call .now() on the Result once your other unrelated code has finished its execution. If you waited for the point when you call .now() to actually initiate the load, you might have your response handler/API method just waiting around for the result, instead of doing useful computations.
Finally, the conceptual link between .now() for loading and .now() for saving is that both operations happen in the background, and are only finally forced, waiting the execution thread, when .now() is called on the Result-interface-implementing object that is returned by the call to save() or load().
I hope this has helped explain the asynchronous constructs in Java Objectify for you. If you have any further questions or issues, feel free to include these in your reply, and I'll be happy to help.
Sincerely,
Nick Technical Solutions Representative Cloud Platform Support
[1] http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
[2] http://objectify-appengine.googlecode.com/svn/trunk/javadoc/com/googlecode/objectify/Result.html
The Google Cloud Datasore
was designed to give the user a positive relational and non-relational experience, essentially the best of both worlds. Google datastore is a NoSQL database which offers eventual consistency for improved scalability but also gives you the option to choose strong consistency.
This article by Google, Balancing Strong and Eventual Consistency with Google Cloud Datastore, will go a long way to answering some of your questions. It explains the eventual consistency model which is key to understanding how the datastore works under the hood in relation to your question.
Asynchronous operations start a network fetch to the backend and then let your code continue executing. The advantage of async operations is that you can run several of them in parallel:
Result<Thing> th1 = ofy().load().key(thingKey1);
Result<Thing> th2 = ofy().load().key(thingKey2);
Result<Thing> th3 = ofy().load().key(thingKey3);
th1.now();
th2.now();
th3.now();
This executes significantly faster than calling now()
immediately each time. Note this is a bad example because you probably would use a batch get (which also parallelizes the operation) but you can have several queries, saves, deletes, etc running simultaneously.
now()
always forces synchronous completion, blocking until done.