[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[jetty-users] problem with continuation reuse - how to sync timeout with async task?
|
I'm using jetty-8 (embedded) and have a servlet that upon request starts
some (lengthy) computation in the background and wants to return this to
the user after completion.
I try to use the
https://wiki.eclipse.org/Jetty/Feature/Continuations#Suspend_Continue_Pattern
(even though the problem will exits also with suspend/resume).
The problem occurs when I set a timeout (I just want the task to wait a
certian amaount of time for completion and cancel it then):
If the continuation times out I send an error back to the client (see
code below), but my async task still holds a reference to the
continuation. Since jetty reuses the continuation object after timeout,
when the task now finished and tries to contine the continuation I get
problems since
a) The continuation is reused but for a completely different request
b) The continuation is reused but not reasigend yet
This mainly leads to weird exceptions and since the continuation is
reused I even can't avoid them by query continuation state.
Is there any option/workaround to circumvent this or diable continuation
recycling? Or must all access to the continuation be syncronized in some
way? I attached the basic code I use in the servlet and two of the
exceptions I see, note that normally all works fine, just in high load
where timouts occur there is where the problem arises.
Code:
final Continuation continuation = ContinuationSupport.getContinuation(req);
if (continuation.isExpired()) {
// Timout, provider has taken too long to succeed
if (!resp.isCommitted()) {
resp.addIntHeader("Retry-After", WORKER_TIMEOUT * 2);
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
return;
} else {
continuation.setTimeout(TimeUnit.SECONDS.toMillis(WORKER_TIMEOUT));
continuation.suspend(resp);
executorService.submit(new BackgroundTask(continuation));
}
java.lang.IllegalStateException: IDLE,initial
at
org.eclipse.jetty.server.AsyncContinuation.complete(AsyncContinuation.java:579)
~[na:na]
at BackgroundTask.run() <-- This is the background worker...
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown
Source) [na:1.7.0_67]
at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown
Source) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown
Source) [na:1.7.0_67]
at java.lang.Thread.run(Unknown Source) [na:1.7.0_67]
java.lang.IllegalStateException: REDISPATCHED,resumed,expired
at
org.eclipse.jetty.server.AsyncContinuation.complete(AsyncContinuation.java:567)
~[na:na]
at BackgroundTask.run() <-- This is the background worker...
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown
Source) [na:1.7.0_67]
at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown
Source) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown
Source) [na:1.7.0_67]
at java.lang.Thread.run(Unknown Source) [na:1.7.0_67]