How to identify either request completed or channel closed for HTTP/1.1 keep-alive

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
Hi,
Looking for a way to identify either the request is completed (context.onClose called) or underlying channel closed (context.getDirectChannelAccess().getChannel().closeFurture() called) when using HTTP/1.1 keep-alive sockets.

Issue if the channel is closed in that case context.onClose() is not getting called.

I wrote a function to identify the request completion, but the request processing getting halted post its execution -- probably due to ratpack continuation semantics:

public static Promise<? super Context> onComplete(Context context) {
        Promise<? super Context> completePromise = Promise.of(downstream -> {
            context.onClose(requestOutcome -> downstream.success(context));
        });
        Promise<? super Context> closePromise = Promise.of(downstream -> {
            context.getDirectChannelAccess().getChannel().closeFuture().addListener(future -> downstream.success(context));
        });

        return RxRatpack.promiseSingle(Observable.merge(RxRatpack.observe(completePromise), RxRatpack.observe(closePromise)).single());
    }
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

danhyun
Hi there Bingo,

Are you trying to perform an action upon request completion?

If so there is mechanism `Response#beforeSend(Action<? super Response>)` that will execute the action before sending response to the client

https://ratpack.io/manual/current/api/ratpack/http/Response.html#beforeSend-ratpack.func.Action-
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
But that won't help in identifying whether the channel closed or last byte of the response sent.
In case afterSent method would be available?
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

danhyun
That's a good point.

I'm curious to the use case here but to offer another suggestion you may be able to fork execution so that you can continue after execution is complete https://ratpack.io/manual/current/api/ratpack/exec/ExecController.html#fork--
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
Can you please point me to more documentation about the fork method -- what it does, how it does.
ExecController.html#fork is having no documentation.
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

Luke Daley
Administrator
Hi Bingo,

We don’t have a well polished hook for this kind of thing right now. What are you intending to use such a hook for?
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
I was trying to call a method only once, either when the context completed (response sent) or the channel is closed.

But due to HTTP/1.1 keep-alive, single channel can serve multiple requests (multiple contexts gets created), there doesn't seem to way to call it only once without maintaining an external state per channel.

I tried writing a utility using Observable and promise (as given in the previous post), but that somehow hangs the execution of the request processing (via handler chain) -- probably my lack of understanding of ratpack execution model (sorry for that).

Would be helpful if you can point to some documentation describing ratpack execution model in details.

I went through these articles but still seems to be uncomfortable with ratpack execution model:
http://ldaley.com/post/97376696242/ratpack-execution-model-part-1
http://ldaley.com/post/102495950257/ratpacks-execution-model-in-practice
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
In reply to this post by Luke Daley
To make the use case concrete, we are using it to free a shared backend resource if either one of the event (context served or channel closed) happen, which otherwise would be kept held.
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
In reply to this post by Luke Daley
Hi Luke,
Got a good insight into ratpack internals from your excellent talk at gr8conf:
https://www.youtube.com/watch?v=WT8S-dMLSVM

Have couple of questions, if you can help in:
1. So new Execution can be forked when one wants to have a separate error handler ( similar to try/catch ), or any other use case?
2. Any insight how the executions are maintained within ratpack?


Thanks in advance!
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

Luke Daley
Administrator
Hi Bingo,

You can think of an execution as a logical operation; responding to a request for example. In synchronous programming, the contiguous slice of time (and call stack) that you are using a thread to do such a thing is analogous. In async programming, we have to give the thread up when we don’t have CPU bound work to do. Therefore, we need another construct to model a logical operation.

You can fork an operation whenever you want to perform a logical operation. When you are responding to requests, you are already inside an execution because Ratpack has done this for you (see: https://github.com/ratpack/ratpack/blob/2ff91020c8948a5eb4c59aa1acf0824190d460ab/ratpack-core/src/main/java/ratpack/handling/internal/DefaultContext.java#L165-L165). If you are doing any kind of background processing then you’ll want to fork executions. Or, if you want to do some concurrent processing within your request handling then you might need to fork executions (if the concurrent pieces of work do async work or require Ratpack promises etc.).

The gory details of how executions work are in the DefaultExecution and DefaultExecController classes.

If you are just trying to pool a resource, the Execution.onComplete() callback (https://github.com/ratpack/ratpack/blob/f275fe482b05406e1911f9227c3c83b4b380488d/ratpack-core/src/main/java/ratpack/exec/Execution.java#L133-L133) might be appropriate.

You could write something like this:

Thing obtainThing() {
Thing thing = thingPool.get()
        Execution.current().onClose(() -> thingPool.give(thing))
        thing

That will work fine, as long as you don’t need to pass the `thing` across execution boundaries where receiving execution lives longer than the owning execution.

On 4 April 2016 at 4:53:41 PM, bingo [via Ratpack Forum] ([hidden email]) wrote:

Hi Luke,
Got a good insight into ratpack internals from your excellent talk at gr8conf:
https://www.youtube.com/watch?v=WT8S-dMLSVM

Have couple of questions, if you can help in:
1. So new Execution can be forked when one wants to have a separate error handler ( similar to try/catch ), or any other use case?
2. Any insight how the executions are maintained within ratpack?


Thanks in advance!


To start a new topic under Ratpack Forum, email [hidden email]
To unsubscribe from Ratpack Forum, click here.
NAML
Reply | Threaded
Open this post in threaded view
|

Re: How to identify either request completed or channel closed for HTTP/1.1 keep-alive

bingo
Thanks Luke. It worked!