-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
obtaining the stream state #4428
Comments
Here's an API proposal: We add a new method to the type StreamState int
// TODO: define constants for all stream states defined in RFC 9000
type {Send,Receive}Stream interface {
StateTransition() <-chan StreamState
} The channel returned here is a buffered channel, with a capacity sufficient to hold all possible state transitions. I haven't done the math yet, but 8 should be sufficient, maybe even smaller. The nice property of this channel API is that it doesn't matter when the application calls it: For example, the stream might already be closed when it is called. The channel will then contain all state transitions that happened to reach this state. On the other hand, it requires a Go routine to block on this channel. Maybe it's better to set a callback: type {Send,Receive}Stream interface {
OnStateTransition(func(StreamState))
} This callback would be called multiple times if multiple state transitions had already happened. |
Note that the callback allows us to have multiple layers set a callback. We'd just wrap the existing callback. It's not terribly efficient, but should be fine for a limited number of callbacks. I don't see how this would work with the channel-based API. |
Alternatively, we could consider changing how the QUIC layers reports streams as completed: We could only do that once the STOP_SENDING error (for send streams) or RESET_STREAM error (for receive streams) has been read by the application. This would enforce "correct" usage of the stream API, and allow applications to more easily track the stream state by just wrapping a |
Another downside is that the stream actually needs to be used (read from and written to). It's possible to just open the HTTP stream, and send and receive datagrams, but that means you'll never observe the state transition. |
HTTP Datagrams (#3522) require us to track the state of the underlying QUIC stream:
SendDatagram
in our API.My first idea how to implement this was tracking the state transitions by wrapping a
quic.Stream
. For example, we know that the send side is closed whenClosed
andCancelWrite
are called. So far, so good. However, the send side can also be closed by receiving a STOP_SENDING frame. As a consumer of aquic.Stream
, we'll only learn about this on the next call toWrite
.But here's the problem: What if the application never writes again. Sure - it should not just walk away from the stream without either calling
Close
orCancelWrite
, but there's no guarantee for that. At the QUIC layer, we'd garbage collect the stream, whereas on the HTTP/3 layer this stream would remain open indefinitely.The same happens on the read side, if the application never calls
Read
after the RESET_STREAM has been received. Again, the application shouldn't do that (and risks leaking the stream if it does and no RESET_STREAM is received), but we also don't have a guarantee for that.It would be nice if there was an API that could be used to obtain the stream state, avoid any synchronization issues. It would be even nicer if no
quic.Config
entry was required, since our HTTP/3 API allows using a QUIC connection.The text was updated successfully, but these errors were encountered: