playframework 2.0 - Async Request in (Scala) Play "Hangs" -
i've written application (scala) play , when run on local machine, works expect. method i'm working on (there may others issue, haven't checked extensively) method triggered post request. returns async object because evaluation done method returns future.
but method behaves quite differently when deploy it. i've been chasing down day, i've gotten point have no explanation going on.
the method looks this:
def add = action(parse.json) { request => async { val req = request.body.asopt[taskrequest] map { r => val job = createjob(r) submitjob(job, r) job map { ij => alloworigin(created(ij).withheaders("location" -> routes.jobs.read(ij._id.stringify).url)); } } req.get } }
overall, pretty simple. createjob
method returns future[job]
. submitjob
call kind of "fire , forget" call trigger background stuff (that i'm not interested in waiting for). process job
result produce result
object when job
has been created.
all works described above on local machine. when deploy this, odd happens. submitjob
call triggers long running computation. said, i'm not interested in waiting why don't use future
returns anywhere.
but here's odd part...on development machine, response post request (which directly calls add) comes job created. on deployment machine, response after submitjob
task completed! in other words, i've got req
future
seemingly unrelated submitjob
call (it doesn't depend on outcome), in deployment environment, async
block won't return until submitjob
complete (even though req
fulfilled immediately).
what heck going on here? i've put println
statements through code. gets past req.get
call immediately. overall (http) response waits until submitjob
done. async
somehow know submitjob
call? if so, why behave differently on 2 different machines?
any ideas?
ok, figured out. oh pain was. issue "fire , forget" task long running task. thread pool size on deployment machine ended being smaller development machine. result, long running task dropped in thread pool , clogged up. processing of asyncresult
presumably preempted long running calculation (it blocking on result long running calculation, bottom line blocked).
after reading nice explanation of futures in scala 2.10 heather miller, noticed blocking
construct can used temporarily expand size of thread pool single future. wrapped blocking code blocking
call , did trick. presumably, allocated additional temporary worker handle blocking call and, result, asyncresult
stuff got processed in timely manner.
(note, wrapping submitjob
call useless because that, itself, didn't block. had go submitjob
call , find place actual blocking , wrap that.)
Comments
Post a Comment