ResponseBody protocol and non-blocking writes

Skip to first unread message

James Reeves

Jul 9, 2016, 11:18:28 AM7/9/16
to Ring
I'd like to get some feedback on handling non-blocking writes in Ring. This is something that I intended to leave until Ring 1.7.0, and it still seems likely this will be the case, but I'm raising the discussion earlier, because it may affect the current ResponseBody implementation, and because testing with a real implementation has made me reconsider how we can approach this.

In Ring 1.6.0-beta2, the ResponseBody protocol is currently defined:

  (defprotocol ResponseBody
    (write-body [body output-stream]))

Using an OutputStream complements the InputStream of the request body, and all Java web servers support it. With synchronous handlers, the OutputStream can be closed by the web server once the handler has terminated. With asynchronous handlers, we need another way of indicating we're done with the stream.

The most obvious option to signal we're done is to close the stream, and indeed that's how the design currently works. There is a bug that prevents this from working in beta2, but it's fixed locally pending testing.

However, I'm uncertain whether this approach is complecting the idea of closing the output stream and closing the response. Potentially they're not the same thing.

Alternatively we could extend the protocol with a "close" function:

  (defprotocol ResponseBody
    (write-body [body output-stream close]))

This means that the closing the output-stream is redundant, which makes me wonder if we can replace the output-stream with a writer function:

  (defprotocol ResponseBody
    (write-body [body write close]))

Which naturally suggests factoring it out into writer protocol.

  (defprotocol ResponseBody
    (write-body [body writer]))

  (defprotocol ResponseWriter
    (write [writer data])
    (close [writer]))

At first glance this seems like we're just reimplementing the output-stream, and that certainly accounts for a lot of my hesitation around this design. The advantage is that it can be extended to support an NIO approach:

  (defprotocol ResponseWriter
    (write [writer data] [writer data on-success on-error])
    (close [writer]))

NIO in Java web servers is a thorny problem, because every web server has its own unique implementation. This is a problem I wanted to push back to a future release, but if altering the design for 1.6.0 can make 1.7.0 easier, it's worth considering.

- James
Reply all
Reply to author
0 new messages