-
Notifications
You must be signed in to change notification settings - Fork 157
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
[RFC] Implement "related events" API. #238
Conversation
Thanks for taking a swing at this! Really appreciated! 👍
Why did you choose this behaviour? Sounds strange to me - on first thought... I have my API-user hat on at the moment: Since you already have a very nice and comprehensive definition of which events can be related with each other (in your test comments) - how about baking this directly into the events? Or maybe I just have a very simplistic view for a general purpose API design? 😄 |
Yeah, so this is a thing I've been thinking about. What I'm most worried about is the question of aliasing. Specifically, if we emit This isn't so bad with One possibility is to have events have specific flags for their possible related events (e.g. a Otherwise, I can't see a system based on "aggregating" events that isn't awkward. Frankly, the least awkward mode here might be to hang the triggering frame off any event fired by that frame. That at least gives mitmproxy what it needs to rebuild equivalent frames, though we again need to worry about the wacky internal gymnastics h2 performs with regard to HEADERS frames. |
Sounds good! I'm not sure how other people are receiving data and passing it to h2, but in mitmproxy we only read one frame at a time, and process it. This makes dealing with events much simpler, because it keeps the dependencies between streams limited. |
How are you ensuring you read only one frame? |
We are parsing the frame header and then read the exact length of the frame from the socket. |
Ok, that makes sense. I think that's a relatively unusual approach: most implementations will just feed bytes directly into the state machine without checking where frame boundaries are. Similarly, however, most implementations don't really care about simultaneity except as it might cause unexpected So I remain a bit unsure about how best to move this forward, but we can also prototype the interface based on set properties and see how the implementation there looks. |
Alright, we decided to go with #240 instead. |
This is a potential solution to #234.
The problem we're trying to address here is twofold. Firstly, users like mitmproxy (represented by @Kriechi and @mhils) have a desire to reproduce frames as accurately as possible when they proxy the connection. This means that it's important to them to tell the difference between the two frame sequence of frames that goes
[HEADERS(END_HEADERS), PRIORITY]
and the one frame one that goes[HEADERS(PRIORITY, END_HEADERS)]
.Secondly, we want to begin to introduce to hyper-h2 this notion of events happening "simultaneously": that is, where multiple state transitions happen in such a way that they all occur at the same time, meaning that the user cannot reliably determine the allowed actions unless they have processed all the events that were emitted at that time. Mostly this is a pretty benign issue, but it would be nice to lazily consume events rather than emit them all at once (see #228 for more on this).
That makes this change both an attempt to address the first point cleanly and a potential precursor to the second. In essence, you can think of this change as something of a "beta" API for one of the proposed changes in #228.
In this specific change, events that can semantically occur simultaneously with each other now carry a
related_events
property. This property is afrozenset
(immutability is good!) of all the events that occurred simultaneously.This PR is a RFC because I'm not 100% sure I'm happy with the API as it stands. In particular, there are a few warts that I'd like feedback on.
related_events
fields. This is done primarily for clarity (to suggest that only some events can be affected by simultaneity), but it potentially means that code that works with the events gets pretty ugly, because sometimes accessingevent.related_events
will raise anAttributeError
, based only ontype(event)
. So we may want to addrelated_events
to all events.related_events
contains afrozenset
of all the events that occurred at once, meaning thatevent in event.related_events
is alwaysTrue
. That's simple and requires the least work in the lower-level library (which is good, because this is a hot section of code), but it leads to the possibility of surprises if the event is handled incautiously (e.g. if you processevent
and then processevent.related_events
you may processevent
twice). So we may want to create different frozensets for each event.Anyway, I'd like people's feedback on this. @python-hyper/contributors, can I get your input here?