jooby icon indicating copy to clipboard operation
jooby copied to clipboard

In case of async route handlers, after() runs before the handler, not after it

Open cbxp opened this issue 3 years ago • 3 comments

Example with Kotlin coroutines:

    before {
      println("Before handler")
      ctx.onComplete {
        println("After response sent")
      }
    }

    after {
      println("After normal handler, but BEFORE suspend handler")
    }

    coroutine {
       get("/") {
          println("After already executed at this point")
          "Hello"
       }
    }

There is a workaround to use onComplete, but it runs after the response has been sent and in a different thread.

The same problem is also with e.g. returning a CompletableFuture from Java route handler, and probably others that use DetachHandler.

cbxp avatar Nov 16 '21 13:11 cbxp

Yea, non-blocking types don't work well with filters. It is documented here: https://jooby.io/#responses-nonblocking-limitations

jknack avatar Nov 18 '21 11:11 jknack

@jknack with Kotlin coroutines it would be easy to guarantee the execution pipeline.

Otheriwse, it's hard to control things like transactions. The transaction handling example in the docs don't work with async requests at all. Probably you should add there an info that global transaction handling is not possible for non-blocking requests currently...

I tried putting transaction handling into onComplete(), but there are problems with it:

  • Transaction is closed (committed/rolledback) after the response is sent, therefore it is possible for the subsequent request to "see" old DB state.
  • In case of errors and rollback, again, you cannot unsend the response.

I tried looking at CoroutineLauncher and see if filters could be run there, but the current routing model doesn't allow for it easily...

cbxp avatar Nov 28 '21 09:11 cbxp

I want to revisit and see if we can improve it. Ideally, would like do the same for completable future

jknack avatar Dec 10 '21 12:12 jknack

@cbxp @angryziber how do you share ThreadLocal between coroutine scope?

jknack avatar Dec 14 '22 12:12 jknack