-
Notifications
You must be signed in to change notification settings - Fork 84
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
filters: support internal buffering #1090
Conversation
c78828f
to
c885cb7
Compare
switch (status) { | ||
case Http::FilterDataStatus::Continue: | ||
if (iteration_mode_ == IterationMode::Stopped) { | ||
// Error: iteration must be Resumed first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we planning to add an error here or will we silently fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options are to fail the request or crash the app. Neither seems terribly ideal, but perhaps neither is silently failing. I hadn't made up my mind here yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the place for an assertion? i.e the contract is that if the FilterDataStatus is to continue it is a programming error to have the manager's iteration_mode as anything but ongoing?
Related. Can we write API docs for the programming contract that these filters have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ Yeah, after going through this section in it entirety I think we need some more comments about all the combinations and why we are treating them as we are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed about public documentation (there's an issue tracking it) - also this is currently captured in the planning doc I shared when we decided on this behavior. Whether and how it's a programming error is something I'm still ambivalent about. We could also generate an error response, too. Or do nothing here, and let Envoy do whatever it does when requests/responses try to forward invalid state. I'm going to make this a TODO I think for now.
break; | ||
case Http::FilterDataStatus::StopIterationAndBuffer: | ||
if (iteration_mode_ == IterationMode::Stopped) { | ||
// Data has already have been buffered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use the no buffer variant here because the data is being buffered in this filter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments!
@@ -29,6 +29,8 @@ class PlatformBridgeFilterConfig { | |||
|
|||
typedef std::shared_ptr<PlatformBridgeFilterConfig> PlatformBridgeFilterConfigSharedPtr; | |||
|
|||
enum class IterationMode { Ongoing, Stopped }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: The filter manager in envoy defines this as IterationState. Should we keep the same language here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly internally Ongoing/Continue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we now have a Resume
status, I felt Ongoing
was a bit clearer. Iteration will be ongoing or iteration will be stopped. I'm fine with IterationState
though.
internal_buffer->move(data); | ||
in_data = Buffer::Utility::copyToBridgeData(*internal_buffer); | ||
} else { | ||
in_data = Buffer::Utility::copyToBridgeData(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe this will become clear later, but why is this a copy rather than a drain like before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the buffer is unmodified, we shouldn't be draining Envoy's buffer. Per our discussed API, we now explicitly disallow the buffer to be modified in any state other than Continue
or Resume
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also other ways we could potentially handle this, but for now, this is expedient and has no real downside since transform was doing a copy anyways.
switch (status) { | ||
case Http::FilterDataStatus::Continue: | ||
if (iteration_mode_ == IterationMode::Stopped) { | ||
// Error: iteration must be Resumed first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the place for an assertion? i.e the contract is that if the FilterDataStatus is to continue it is a programming error to have the manager's iteration_mode as anything but ongoing?
Related. Can we write API docs for the programming contract that these filters have?
break; | ||
case Http::FilterDataStatus::StopIterationAndBuffer: | ||
if (iteration_mode_ == IterationMode::Stopped) { | ||
// Data has already have been buffered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Data has already have been buffered. | |
// Data has already have been buffered by the PlatformBridgeFilter. |
Just want something more explicit about whose responsibility it is to buffer
iteration_mode_ = IterationMode::Stopped; | ||
break; | ||
default: | ||
PANIC("unsupported status for platform filters"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convention is to use NOT_REACHED_GCOVR_EXCL_LINE
. You can leave a comment above why the default should not be reached.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the default
can be reached - we haven't enumerated all statuses Envoy defines, and a truly strange implementation of a filter could try to break things here. I think the assertion is maybe warranted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@goaway, under the hood NOT_REACHED_GCOVR_EXCL_LINE
panics. It doesn't mean that it cannot be reached, it means that if it reaches it is an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ bump on this
// TODO(goaway): Current platform implementations expose immutable data, thus any modification | ||
// necessitates a full copy. Add 'modified' bit to determine when we can elide the copy. See also | ||
// https://github.com/lyft/envoy-mobile/issues/949 for potential future optimization. | ||
data.drain(data.length()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm were we double draining before? Once in toBridge data and once here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we were double draining before. Which was benign, but not ideal.
switch (status) { | ||
case Http::FilterDataStatus::Continue: | ||
if (iteration_mode_ == IterationMode::Stopped) { | ||
// Error: iteration must be Resumed first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ Yeah, after going through this section in it entirety I think we need some more comments about all the combinations and why we are treating them as we are.
@junr03 I tried to make comments a little bit more explicit. Let me know if you have other suggestions. In general, I agree on the need for holistic documentation of all this, but I do think the tests ultimately also make explicit the intended behavior. |
Yeah that helps internally. I also worry about platform filter authors. But happy to see in a subsequent PR per your other comment |
Looks like ASAN is still failing on the latter two tests. Just need to release the received data in the callback I think |
@junr03 I actually am releasing it. Not sure why it's still failing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comments and the todo. Just one small bump on the panic, otherwise lgtm.
iteration_mode_ = IterationMode::Stopped; | ||
break; | ||
default: | ||
PANIC("unsupported status for platform filters"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ bump on this
Signed-off-by: Mike Schore <mike.schore@gmail.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com>
5499521
to
3ffd978
Compare
Description: Adds internal buffering support for platform filters. Filters may now utilize Envoy's internal buffering by returning the status StopIterationAndBuffer. The complete buffer will be passed on subsequent on*Data invocations until iteration is resumed. This change does not support modifying the buffer (support coming in #1100 ).
Risk Level: Moderate
Testing: Unit coverage, local and CI
Signed-off-by: Mike Schore mike.schore@gmail.com