Open ShawnROGrady opened 2 years ago
Thanks for opening an issue, and for the kind words.
I agree with you. These should definitely be handled better. A few thoughts:
assert false
in cases that are unreachable (e.g. we can't respond_with_streaming
on a Reqd.t
that hasn't been surfaced by the API)assert false
s that are placeholders for TODO
items.unit
, we could return (unit, stream_state) result
for some values of stream_state
like Closed
, etc
b. we could create an exception Stream_closed
and fail in these casesReqd
API close to http/af so that it's easier to abstract away in piafBoth alternatives above are technically breaking changes, so I think we get to pick. Do you see other alternatives?
100% agreed on point 1, I think something like an assert false
or failwith
is a good way to indicate a failure due to something reaching a theoretically unreachable state.
For point 3, I personally like result
since it makes it clear from the API that the operation may fail in expected cases, but realistically I understand that raising an exception may be more ergonomic. Mainly, I would think it might be a good idea to go with option b (using an exception) until the API finalized.
For your last point, this is a bit difficult for me since I don't have much low-level experience of directly interacting with transport protocols. I mainly use go and HTTP/1 at my day job (whose server-side request cancellation detection appears to come from a and b), and I know .NET has something similar (but I have no experience with), so to me the approach I think would be easiest for consumers would be to make this property accessible from the request context. Either through H2.Reqd.t
or through a promise passed to ~request_handler
. Mainly such an approach would allow the server to propagate cancellation down the stack, such as in a situation where the server makes another outgoing request, but from my understanding this would definitely require the most changes to the server-side logic.
To me, adding something like exception Stream_closed
seems like the best solution for now to allow servers to gracefully handle while not blocking future versions from solving the problem a different way.
EDIT:
My main thoughts come from me not being fully comfortable with what the API should look like. To me, using exception Stream_closed
doesn't feel like the ideal solution, but it would allow servers to gracefully handle this case currently while allowing a different solution to be added in the future.
H2.Reqd
fails various operations (respond_with_streaming
,schedule_trailers
, others) if the client closes the stream, but currently it doesn't look like there's a way for the for a server implementation to avoid/handle these failures.I would think the clearest way to propagate cancellation would be to make
~request_handler
for the lwt/async server implementations accept a promise which is resolved/rejected when the stream is closed. However that might require a version bump, so it might be simpler to just raise an exception other thanFailure
(such as currently the case with schedule_trailers) orAssert_failure
(currently the case with respond_with_streaming) when trying to respond on a closed stream. Making the server explicitly catch aFailure
orAssert_failure
seems like a bad idea, since we would unintentionally catch actual unexpected errors, but this seems like an expected case that a server should be able to gracefully handle.I'm a huge fan of this project, and thank you for all of your work (I'm fairly new to ocaml and have found this project incredibly approachable), so sorry if this is something that's already possible that I missed.