-
Notifications
You must be signed in to change notification settings - Fork 1
Execution context in Play!
"An execution context is basically another name for a thread pool"
In play we can use more than one execution contexts. Default execution context is used by Play see more. This context use just for non-blocking and no long computation !
For blocking and long computations create and use your own execution context !
Why is it so ? Its because blocking and long computation can really slow down Play at all !
For promises we can tell which execution context must it use. See Promise.promise implementation. Actually in Promise.promise we cann run long computations (Play creators recommend that)
public static <A> F.Promise<A> promise(F.Function0<A> var0, ExecutionContext var1) {
return FPromiseHelper.promise(var0, var1);
}
But Promise.promise is not one with ExecutionContext parameter. See next code.
public F.Promise<Result> selectOneFriend(long id) {
return F.Promise.promise(() -> dao.selectOneFriend(id) ,jpaExecContext) // non-blocking with F.Promise.promise
.map((x) -> x == null ? "" : x, jpaExecContext)
.map(Json::toJson, jpaExecContext)
.map(jsonResponse -> (Result) ok(jsonResponse), jpaExecContext)
.recover(t -> badRequest(t.getMessage() + "\n"), jpaExecContext);
}
Here we are using jpaExecContext that we will create a meanwhile. for all computations, that means whole code, all 5 calls runs in jpaExecContext ! That means now we see at least Promise.promise, recovery and map methods which can run in different execution context.
In this case, we are using Akka to create the ExecutionContext, but you could also easily create your own ExecutionContexts using Java executors, or the Scala fork join thread pool, for example.
# execution context for blocking jpa in this service
jpa-execution-context {
thread-pool-executor {
core-pool-size-factor = 10.0
core-pool-size-max = 10
}
}
public class Application extends Controller {
private static final ExecutionContext jpaExecContext;
static {
jpaExecContext = HttpExecution.fromThread(
Akka.system().dispatchers().lookup("jpa-execution-context"));
}
...
Here you can see that actually responsible for creating contexts is ** Akka !**
Watch out !! Question ? On how many execution contexts perform method selectOneFriend ? Answer is two ! Default plays and in jpaExecContext will run just dao.selectOneFriend(id). Actually i guess this is enough because just dao.selectOneFriend(id) is blocking !!!
public F.Promise<Result> selectOneFriend(long id) {
return F.Promise.promise(() -> dao.selectOneFriend(id) ,jpaExecContext) // non-blocking with F.Promise.promise
.map((x) -> x == null ? "" : x)
.map(Json::toJson)
.map(jsonResponse -> (Result) ok(jsonResponse))
.recover(t -> badRequest(t.getMessage() + "\n"));
}
- for blocking and long computations is better create new execution context
- example code worked for me also without it but ...