[undertow-dev] scala, activate, nio, async jdbc, future, threads

Laurent Bedubourg laurent at labe.me
Sat Dec 13 02:58:51 EST 2014


Thank you very much Jason, it helps me a lot.

One last remark regarding "you can save yourself a worker thread and reuse
the thread they generate the callback from. At that callback point you can
write your response out to the exchange."

When I try to do this, calling x.getResponseSender().send(str) un the
onSuccess callback of the database future, I got an exception
java.lang.IllegalStateException:
UT000004: getResponseChannel() has already been called.

I imagine that the response has already been somehow cleaned up / modified
/ terminated by Undertow when the handler exited (I use
SessionAttachHandler, date() and routing() in my test).

I could not find a way to tell Undertow that I would handle the exchange
and end it manually.

I am using undertow 1.1.1-final maybe this has been fixed since this
version?

Thanks again

Laurent



On Sat Dec 13 2014 at 4:57:33 AM Jason Greene <jason.greene at redhat.com>
wrote:

> Hello Laurent,
>
> Your hunch is correct. You never want to block the I/O thread as each
> thread is shared between many connections, and a pause prevents them from
> being processed. It’s totally reasonable to call dispatch(), which
> transfers the exchange to the worker pool where you can wait on a database
> reply, and in fact this is a normal pattern. The worker pool is sized to be
> pretty large as its expected to host lots of waiters. You can of course
> tweak this, or dispatch to your own special pool if you like. The big
> advantage to an async database call, even with requiring a worker thread,
> is that you can do other work while its running if your pattern fits (e.g.
> parallel db calls, iterative computation, etc).
>
> Alternatively, if the database provides a callback on complete option, you
> can save yourself a worker thread and reuse the thread they generate the
> callback from. At that callback point you can write your response out to
> the exchange.  Just note, that the thread policy of an exchange is that
> only one thread at a time can interact with it. If you have a use case
> where the a request bounces back and forth (e.g. a very long stream
> containing multiple records that must be written to the database as they
> com in), then you will need to coordinate locking around that. Such
> use-cases though should be weighed against the simplicity of just blocking
> in a worker thread.
>
> To answer a second question you have in a comment from your example,
> startBlocking() just enables the use of a plain inputstream/outputstream,
> which can only be done once you have dispatched and blocking i/o is now ok.
>
> Hope this helps,
>
> -Jason
>
> > On Dec 12, 2014, at 3:44 PM, Laurent Bedubourg <laurent at labe.me> wrote:
> >
> > Ok, I think my mail could be reduced to :
> >
> > Is it possible possible to transfer the HttpServerExchange
> responsibility to another thread ?
> >
> > Regards
> > Laurent
> >
> >
> > On Fri Dec 12 2014 at 7:11:01 PM Laurent Bedubourg <laurent at labe.me>
> wrote:
> > Hello,
> >
> > I am evaluating Undertow and trying to fit an async database (with
> scala, Activate and https://github.com/mauricio/postgresql-async which
> use netty and nio).
> >
> > The good news is that it more or less works.
> >
> > My main concern is that the database system create threads using scala
> futures and that I am forced to "Await" for the result of my Futures to
> send the result to the HttpServerExchange.
> >
> > I am forced to dispath() the request because Await locks the current
> thread and I shouldn't lock the IO thread from my Handler, should I?
> >
> > It made me wondering : is is really a good idea to use futures + Await
> with undertow and more generaly nio?
> >
> > If the thread pool is limited and I lock threads, even if the database
> driver is async and uses nio, am I bitting my own leg?
> >
> > Thanks for any input you can give me and sorry if it's too scala related
> :)
> >
> > Regards
> > Laurent
> >
> > PS: Here's the handleRequest I am using to test this, any comment or
> help welcome too since I am discovering the API.
> >
> > def handleRequest(x:io.undertow.server.HttpServerExchange){
> > if (x.isInIoThread()){
> >   x.dispatch(this)
> >   return
> > }
> > // useful or not? no change
> > // x.startBlocking()
> >
> > // Ok, we are in worker thread we can work a little with database
> > // val f = asyncTransactionalChain { implicit context =>
> > //   for (
> > //     a <- asyncTransactional { new AMember("aaa") };
> > //     b <- asyncById[AMember](a.id)
> > //   ) yield b
> > // }
> >
> > // Simulate database work with just a future
> > val f = future {
> >   Some(1)
> > }(scala.concurrent.ExecutionContext.Implicits.global)
> >
> > // send string to xchange
> > def sendReply(str:String){
> >   x.getResponseHeaders().put(io.undertow.util.Headers.CONTENT_TYPE,
> "text/plain")
> >   x.getResponseSender().send(str)
> >   // x.endExchange()
> > }
> >
> > // // this fails
> > // f.onSuccess {
> > //   case Some(result) => sendReply(result.toString)
> > // }(scala.concurrent.ExecutionContext.Implicits.global)
> >
> > // // this works
> > val result = Await.result(f, Duration(1000, MILLISECONDS))
> > sendReply(result.toString)
> > }
> >
> > _______________________________________________
> > undertow-dev mailing list
> > undertow-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/undertow-dev
>
> --
> Jason T. Greene
> WildFly Lead / JBoss EAP Platform Architect
> JBoss, a division of Red Hat
>
>
> _______________________________________________
> undertow-dev mailing list
> undertow-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/undertow-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/undertow-dev/attachments/20141213/885f8ef7/attachment-0001.html 


More information about the undertow-dev mailing list