Skip to content

Conversation

@easwars
Copy link
Contributor

@easwars easwars commented Oct 10, 2025

Existing behavior:

  • At routing time, when an RPC matches a route and a cluster is selected, the interceptor chain for that specific RPC is built.
  • This chain is built on a per-RPC basis.
  • A subsequent RPC that matches the exact same route and cluster will trigger the entire chain reconstruction again, even if no configuration has changed.

New behavior:

  • The interceptor chain is now pre-built for every route and every pickable cluster associated with that route.
  • The chains are constructed once when the config selector is built.

Other changes:

  • Existing unit tests have been converted to be more e2e style tests.
  • This lays the necessary groundwork for upcoming changes to the filter API, specifically to support filter state retention

RELEASE NOTES: NONE

@easwars easwars added Area: xDS Includes everything xDS related, including LB policies used with xDS. Type: Internal Cleanup Refactors, etc labels Oct 10, 2025
@easwars easwars added this to the 1.77 Release milestone Oct 10, 2025
@easwars
Copy link
Contributor Author

easwars commented Oct 10, 2025

@eshitachandwani : FYI this might conflict with your resolver changes for A74. And since you have been looking at the resolver code for sometime now, it would be a good PR to review.

@codecov
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

❌ Patch coverage is 38.63636% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.13%. Comparing base (8110884) to head (433ed3c).

Files with missing lines Patch % Lines
internal/xds/resolver/serviceconfig.go 35.48% 12 Missing and 8 partials ⚠️
internal/xds/resolver/xds_resolver.go 46.15% 4 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8641      +/-   ##
==========================================
- Coverage   79.45%   79.13%   -0.32%     
==========================================
  Files         415      415              
  Lines       41339    41425      +86     
==========================================
- Hits        32844    32782      -62     
- Misses       6621     6713      +92     
- Partials     1874     1930      +56     
Files with missing lines Coverage Δ
internal/xds/resolver/xds_resolver.go 66.84% <46.15%> (-14.93%) ⬇️
internal/xds/resolver/serviceconfig.go 53.09% <35.48%> (-32.46%) ⬇️

... and 16 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dfawley dfawley requested review from arjan-bal and removed request for dfawley October 15, 2025 16:17
@dfawley dfawley assigned arjan-bal and unassigned dfawley Oct 15, 2025
@dfawley
Copy link
Member

dfawley commented Oct 15, 2025

@arjan-bal could you review this change, please?

Copy link
Contributor

@arjan-bal arjan-bal left a comment

Choose a reason for hiding this comment

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

Leaving my comments on the non-test code, still reviewing the tests.

// The filter config override maps contain overrides from the route, cluster,
// and virtual host respectively. The cluster override has the highest priority,
// followed by the route override, and finally the virtual host override.
func newInterceptor(filters []xdsresource.HTTPFilter, cluster, route, virtualHost map[string]httpfilter.FilterConfig) (iresolver.ClientInterceptor, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: What do you think about adding an override suffix to cluster, route, and virtualHost? I find it can help with readability, but no worries if you prefer the current naming.

cs := r.newConfigSelector()
cs, err := r.newConfigSelector()
if err != nil {
r.onResourceError(fmt.Errorf("xds: failed to create config selector: %v", err))
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the function return early after calling onResourceError? I'm not sure what happens when a nil config selector is passed to sendNewServiceConfig.

Copy link
Member

Choose a reason for hiding this comment

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

I think we should return early since onResourceError will call sendNewServiceConfig with an erroring config selector, so we should not call sendNewServiceConfig again with a nil config selector (which will set a default config selector in client conn)

Comment on lines +346 to +347
// Should not happen if it passed xdsClient validation.
panic(fmt.Sprintf("filter %q does not support use in client", filter.Name))
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about continuing to return an error here? The method signature already allows for it, so callers presumably have error handling in place. Panicking to crash the process feels like a worse alternative, especially if this is a recoverable error.

fb.logger.Logf("BuildClientInterceptor called with config: %+v, override: %+v", config, override)

if config == nil {
panic("unexpected missing config")
Copy link
Contributor

Choose a reason for hiding this comment

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

In my opinion printing an error to fail the test may be preferred to panicking from a spawned goroutine. The situation seems similar to the style guide recommendation about only calling t.Fatalf from the main test function.

// by the backend, allowing tests to assert that the correct filter
// configuration was applied for each RPC.
type testHTTPFilterWithRPCMetadata struct {
logger logger
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Is there a benefit of using a logger interface here? If not, I think it's simpler to directory store a testing.T here .


func (*testHTTPFilterWithRPCMetadata) IsTerminal() bool { return false }

var _ httpfilter.ClientInterceptorBuilder = &testHTTPFilterWithRPCMetadata{}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think we should add a comment here stating that ClientInterceptorBuilder is an optional interface for Filters to implement so this compile time check ensures the test filter implements it. In my opinion this would help readers.

}
var errStr string
if newStreamErr != nil {
errStr = newStreamErr.Error()
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that we're converting a string to an error, assigning it to testFilterCfg.newStreamErr and converting it back to a string here. Can the error string be stored in testFilterCfg.newStreamErr to avoid these conversions?

}

func (cs *clientStream) Context() context.Context {
return cs.ctx
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to store a context here? Can we return cs.ClientStream.Context() instead?

Comment on lines +290 to +292
if internal.NewXDSResolverWithConfigForTesting == nil {
t.Fatalf("internal.NewXDSResolverWithConfigForTesting is nil")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: We can avoid this check and let the code panic if we don't expect to fail in most cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

There is a bunch of commented code here that probably needs to be removed. Can you please take a look?

@arjan-bal arjan-bal removed their assignment Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: xDS Includes everything xDS related, including LB policies used with xDS. Type: Internal Cleanup Refactors, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants