A few weeks ago, I wrote a blog post about a proposal for WAI 3.0, which would no longer be based on conduit, and therefore be open to various streaming data frameworks. The response I've received so far has been (I think universally) positive, and therefore I'd like to move forward. There was a good discussion on Reddit[1], but I think the mailing list is a better way to come to consensus on a last few points. In particular, there are two questions still up in the air:
1. Twan raised the question[2] of how to deal with the streaming response body. We need the ability to either emit a new Builder, or flush the stream. I believe we have three different interfaces available to choose from:
a. (Maybe Builder -> IO ()) -> IO ()
b. (Builder -> IO ()) -> IO () -> IO ()
c.
data ResponseStream = ResponseStream
{ responseStreamPart :: Builder -> IO ()
, responseStreamFlush :: IO () }
ResponseStream -> IO ()
(a) is probably the simplest, but also likely to be the least efficient. I tend towards choosing (b), since it avoids the need for an extra datatype, but (c) looks cleaner overall.
2. Dan[3] and Stephen[4] both raised issues about how we'd deal with scarce resource allocation when creating a streaming response. Here's a summary:
a. The approach I linked to in the blog came down to the bracket pattern. The downsides of this are (i) a poorly behaving application could call the callback multiple times, and (ii) it complicates the interface.
b. To avoid problem (i), we could use something like the Acquire datatype[5], making the type signature `type Application = Request -> Acquire Response`. I'm overall negative on this, as the goal here is to continue simplifying to standard datatypes.
c. Stephen's suggestion is to include a cleanup action in the ResponseStream constructor. My primary concern here is that it will be very difficult for application authors to write async-exception-safe code, vs option (a) which makes it trivial.
On both of these questions, new ideas are certainly welcome.