Skip to content

Converting match_delegate filter and composite filter as dual filter.#32777

Closed
yanjunxiang-google wants to merge 4 commits intoenvoyproxy:mainfrom
yanjunxiang-google:match_delegate_dual
Closed

Converting match_delegate filter and composite filter as dual filter.#32777
yanjunxiang-google wants to merge 4 commits intoenvoyproxy:mainfrom
yanjunxiang-google:match_delegate_dual

Conversation

@yanjunxiang-google
Copy link
Copy Markdown
Contributor

Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]

Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>

Factory::MatchTreeValidationVisitor validation_visitor(*factory.matchingRequirements());

Envoy::Http::Matching::HttpFilterActionContext action_context{prefix, absl::nullopt,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an issue to pass in an absl::nullopt into this data object? @wbpcode

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we pass in an absl::nullopt is due to there is no Server::Configuration::FactoryContext object can be retrieved here.

@yanjunxiang-google
Copy link
Copy Markdown
Contributor Author

/assign @tyxia @wbpcode @snowp

…_delegate_dual

Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
@yanjunxiang-google yanjunxiang-google marked this pull request as draft March 7, 2024 23:54
@yanjunxiang-google yanjunxiang-google marked this pull request as ready for review March 8, 2024 20:03
Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
Copy link
Copy Markdown
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution. This lgtm overall. Only two comments are added.

Comment on lines +20 to +31
DualInfo, Server::Configuration::FactoryContext&) {
return createFilterFactory(proto_config);
}

absl::StatusOr<Http::FilterFactoryCb> BufferFilterFactory::createFilterFactoryFromProtoTyped(
const envoy::extensions::filters::http::buffer::v3::Buffer& proto_config, const std::string&,
DualInfo, Server::Configuration::UpstreamFactoryContext&) {
return createFilterFactory(proto_config);
}

absl::StatusOr<Http::FilterFactoryCb> BufferFilterFactory::createFilterFactory(
const envoy::extensions::filters::http::buffer::v3::Buffer& proto_config) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do this in separated PR. Thanks.

Copy link
Copy Markdown
Contributor Author

@yanjunxiang-google yanjunxiang-google Mar 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To convert the match_delegate filter into dual filter, I have to change factory_base.h to have two interfaces of createFilterFactoryFromProtoTyped(), one for Server::Configuration::FactoryContext, and one for Server::Configuration::UpstreamFactoryContext&. Thus I have to change all the existing dual filter implementation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I think the change is because the match_delegate needs to access the original FactoryContext and UpstreamFactoryContext.

Then, rather than changing the DualFactoryBase's methods here, I prefer just to change the match_delegate to avoid inheriting from DualFactoryBase.
Thats say, the match_delegate could inherit the NamedHttpFilterConfigFactory and UpstreamHttpFilterConfigFactory .

If we do think the DualFactoryBase should update it's methods, we can do the refactoring in separated PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean have match_delegate speciall inerit from NamedHttpFilterConfigFactory and UpstreamHttpFilterConfigFactory to do something similar as the DualFactoryBase:

class DualFactoryBase : public CommonFactoryBase<ConfigProto, RouteConfigProto>,
, but slightly different?

I thought all dual filter should inherit from DualFactoryBase based on this note: https://github.com/alyssawilk/envoy/blob/main/source/docs/upstream_filters.md

Copy link
Copy Markdown
Member

@tyxia tyxia Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My 2 cents: I tend to agree with @wbpcode that separate inheritance from NamedHttpFilterConfigFactory and UpstreamHttpFilterConfigFactory is probably a better idea (if this approach works).

Given the uniqueness of match_delegate filter, i think other filters won't need this new API. we can make match_delegate as an exception to that doc.

Copy link
Copy Markdown
Contributor Author

@yanjunxiang-google yanjunxiang-google Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong preference on this. However, if we go that route, and if another filter also has logic based on factory type(NamedHttpFilterConfigFactory/UpstreamHttpFilterConfigFactory), then we will have to make it another exception if we want to convert into dual filter.

Overall, I feel the way current DualFactoryBase method: createFilterFactoryFromProtoTyped() implementation, which only support parameter type ServerFactoryContext, greatly limited its flexibility. We should let it be able to support both FactoryContext and UpstreamFactoryContext, same as createFilterFactoryFromProto() in that class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind ping on this!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. The match_delegate could be a special case. The docs just a recommend way to develop a new dual filter and not a strict rule.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a new PR for this: #33013. In the new PR, the match_delegate filter is inherited from NamedHttpFilterConfigFactory and UpstreamHttpFilterConfigFactory , kind like DualFactoryBase.

auto message = Config::Utility::translateAnyToFactoryConfig(
proto_config.extension_config().typed_config(), context.messageValidationVisitor(), factory);
proto_config.extension_config().typed_config(),
context.serverFactoryContext().messageValidationVisitor(), factory);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, here is the common problem. You cannot use the context.serverFactoryContext().messageValidationVisitor() to replace the messageValidationVisitor() from correct context.


By the way, seems that a skilled envoy developer (from google) even cannot use this messageValidationVistor correctly, so I think we should re-discuss our previous plan to use single messageValidationVisitor(). cc @htuch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments!

Do you mean for downstream context(FactoryContext), it should be context->messageValidationVisitor(), and can not be context.serverFactoryContext().messageValidationVisitor()? Is this messageValidationVisitor two different things or same thing accessed by two different means?

If they are two different things, I can pass in the messageValidationVisitor() from the caller.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They may be different things. 🤣

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wbpcode if you have a proposal to move #31073 forward happy to discuss, I agree there is some inconsistency of use here and it would be worth evaluating options to make it correct-by-default.

Copy link
Copy Markdown
Member

@wbpcode wbpcode Mar 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try to find some free time to do that.

Copy link
Copy Markdown
Member

@tyxia tyxia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Thanks, Yanjun

Could you please take a look at CI failure. I guess AdmissionControlFilter also needs similar change as it is dual filter already

Signed-off-by: Yanjun Xiang <yanjunxiang@google.com>
@wbpcode
Copy link
Copy Markdown
Member

wbpcode commented Mar 17, 2024

/wait

@juanmolle
Copy link
Copy Markdown
Contributor

juanmolle commented Mar 20, 2024

Just one comment, there are some concerns regarding accessing streamInfo at the moment to convert the filter into dual filter. this filter push data into filter_state https://github.com/envoyproxy/envoy/blob/main/source/extensions/filters/http/composite/filter.cc#L143 could that be a problem? if that is the case perhaps this logic could be skiped if it is an upstream config.

@yanjunxiang-google
Copy link
Copy Markdown
Contributor Author

Just one comment, there are some concerns regarding accessing streamInfo at the moment to convert the filter into dual filter. this filter push data into filter_state https://github.com/envoyproxy/envoy/blob/main/source/extensions/filters/http/composite/filter.cc#L143 could that be a problem? if that is the case perhaps this logic could be skiped if it is an upstream config.

Could you please share a little bit background on this?

@juanmolle
Copy link
Copy Markdown
Contributor

juanmolle commented Mar 20, 2024

According to this document https://github.com/envoyproxy/envoy/blob/main/source/docs/upstream_filters.md upstream filters should access streamInfo in preference as const. It does not say it is a must and that was my question about.

ref
Either the filter does not access streamInfo in a non-const way, or you test and document how the filter interacts with hedging and retries. Note that for hedging, a single downstream StreamInfo is accessible in parallel to both instances of the upstream HTTP filter instance, so it must be resiliant to parallel access.

On the other hand as upstream filter that piece of code probably has no sens and could be skipped now and evaluate it later. (probably just keep the matched action is ok on retries to deduplicate it)
https://github.com/envoyproxy/envoy/blob/main/source/extensions/filters/http/common/factory_base.h#L135

Any reason you close the PR. It seams core reviewers agree on this change and I feel it is really useful

@yanjunxiang-google
Copy link
Copy Markdown
Contributor Author

Thanks for the info! I will take a look.

BTW, I closed this PR because some comments above says we should treat match_delegate filter as special case. Thus I created a new PR: #33013. Let's continue the review process under that PR.

@yanjunxiang-google
Copy link
Copy Markdown
Contributor Author

According to this document https://github.com/envoyproxy/envoy/blob/main/source/docs/upstream_filters.md upstream filters should access streamInfo in preference as const. It does not say it is a must and that was my question about.

ref Either the filter does not access streamInfo in a non-const way, or you test and document how the filter interacts with hedging and retries. Note that for hedging, a single downstream StreamInfo is accessible in parallel to both instances of the upstream HTTP filter instance, so it must be resiliant to parallel access.

On the other hand as upstream filter that piece of code probably has no sens and could be skipped now and evaluate it later. (probably just keep the matched action is ok on retries to deduplicate it) https://github.com/envoyproxy/envoy/blob/main/source/extensions/filters/http/common/factory_base.h#L135

Any reason you close the PR. It seams core reviewers agree on this change and I feel it is really useful

I think updateFilterState() in composite filter is needed even the filter is in upstream filter chain.
A couple of reasons:

  1. We probably want to setup the actions filter state for other filters to access.
  2. The filter state has life time as FilterChain, so the filter state will get out-of-life during retries/hedging. So, it won't be an issue in those cases.

@wbpcode could you please confirm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants