Skip to content
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

xds: add ConfigSelector to support RouteAction timeouts #3991

Merged
merged 18 commits into from
Nov 17, 2020

Conversation

dfawley
Copy link
Member

@dfawley dfawley commented Oct 26, 2020

This change is Reviewable

@dfawley dfawley added Type: Feature New features or improvements in behavior no release notes labels Oct 26, 2020
@dfawley dfawley requested a review from menghanl October 26, 2020 22:34
Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 7 of 9 files at r1.
Reviewable status: 7 of 9 files reviewed, 7 unresolved discussions (waiting on @dfawley and @menghanl)


clientconn.go, line 648 at r1 (raw file):

			cc.applyServiceConfigAndBalancer(sc, s.Addresses)
			if configSelector := iresolver.GetConfigSelector(s); configSelector != nil {
				fmt.Println("received non-nil config selector yay")

s/yay/lol


service_config.go, line 108 at r1 (raw file):

}

type retryPolicy = internalserviceconfig.RetryPolicy

Why do we still need this type?
Just use internalserviceconfig.RetryPolicy?


stream.go, line 177 at r1 (raw file):

	rpcConfig := cc.safeConfigSelector.SelectConfig(iresolver.RPCInfo{Context: ctx, Method: method})
	if rpcConfig == nil {
		rpcConfig = &iresolver.RPCConfig{Context: ctx}

Can this save one allocation

var mc serviceconfig.MethodConfig
if rpcConfig != nil {
  ctx = rpcConfig.Context
  mc = rpcConfig.MethodConfig

  // And rpcConfig.OnCommitted???
}

internal/resolver/config_selector.go, line 44 at r1 (raw file):

// RPCConfig describes the configuration to use for each RPC.
type RPCConfig struct {
	Context      context.Context            // passes info to LB Policy Picker

And talk about timeout? It could be overlooked.


internal/resolver/config_selector.go, line 46 at r1 (raw file):

	Context      context.Context            // passes info to LB Policy Picker
	MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC
	OnCommitted  func()                     // Called when the RPC has been committed (retries no longer possible)

This is never called.


internal/resolver/safe_config_selector.go, line 31 at r1 (raw file):

// implementations such that previous values are guaranteed to not be in use
// when UpdateConfigSelector returns.
type SafeConfigSelector struct {

This is only used by the ClientConn, right?

Is it like pick-wrapper (a helper struct for ConfigSelector)? Move it to the grpc package?


internal/resolver/safe_config_selector.go, line 66 at r1 (raw file):

		ccsPtr = ccsPtr2
	}
	defer ccs.wg.Done()

I don't remember all the details now...
Should this be done in OnCommitted()?

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: 7 of 9 files reviewed, 7 unresolved discussions (waiting on @menghanl)


clientconn.go, line 648 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

s/yay/lol

Argh, I swear I deleted all the debugging stuff. Removed.


service_config.go, line 108 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

Why do we still need this type?
Just use internalserviceconfig.RetryPolicy?

Good point. Done.


stream.go, line 177 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

Can this save one allocation

var mc serviceconfig.MethodConfig
if rpcConfig != nil {
  ctx = rpcConfig.Context
  mc = rpcConfig.MethodConfig

  // And rpcConfig.OnCommitted???
}

The compiler should be able to optimize that, but why take chances? Done. Also implemented OnCommitted.


internal/resolver/config_selector.go, line 44 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

And talk about timeout? It could be overlooked.

Done.


internal/resolver/config_selector.go, line 46 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

This is never called.

Done.


internal/resolver/safe_config_selector.go, line 31 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

This is only used by the ClientConn, right?

Is it like pick-wrapper (a helper struct for ConfigSelector)? Move it to the grpc package?

Yes, but I felt like it was more of a generic "config selector" kind of feature, and needs nothing else from grpc. This is in internal anyway, so it could be moved if desired. LMK if you disagree.


internal/resolver/safe_config_selector.go, line 66 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

I don't remember all the details now...
Should this be done in OnCommitted()?

No, that's not necessary. If we know resolver.ClientConn.UpdateState only returns after the old config selector is done being used, then ref counting of the clusters themselves can be done reliably via the resolver.

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 4 of 5 files at r2.
Reviewable status: 7 of 9 files reviewed, 1 unresolved discussion (waiting on @dfawley and @menghanl)


internal/resolver/safe_config_selector.go, line 66 at r1 (raw file):

Previously, dfawley (Doug Fawley) wrote…

No, that's not necessary. If we know resolver.ClientConn.UpdateState only returns after the old config selector is done being used, then ref counting of the clusters themselves can be done reliably via the resolver.

What's the purpose of RPCConfig.OnComitted then? It's always nil now.

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: 7 of 9 files reviewed, 1 unresolved discussion (waiting on @menghanl)


internal/resolver/safe_config_selector.go, line 66 at r1 (raw file):

Previously, menghanl (Menghan Li) wrote…

What's the purpose of RPCConfig.OnComitted then? It's always nil now.

It's only nil if the config selector doesn't set it. But we will use this for the resolver to ref count clusters.

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewable status: 7 of 9 files reviewed, 1 unresolved discussion (waiting on @dfawley and @menghanl)


clientconn.go, line 647 at r2 (raw file):

		if sc, ok := s.ServiceConfig.Config.(*ServiceConfig); s.ServiceConfig.Err == nil && ok {
			cc.applyServiceConfigAndBalancer(sc, s.Addresses)
			if configSelector := iresolver.GetConfigSelector(s); configSelector != nil {

Handle the resolver setting configSelector to nil.

And should it skip the update if the new is same as the old (can be done inside SafeConfigSelector)

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: 7 of 9 files reviewed, 1 unresolved discussion (waiting on @menghanl)


clientconn.go, line 647 at r2 (raw file):

Previously, menghanl (Menghan Li) wrote…

Handle the resolver setting configSelector to nil.

And should it skip the update if the new is same as the old (can be done inside SafeConfigSelector)

Done for the first one.

It's unclear whether the second suggestion is worth doing. It requires an extra atomic read for every call, but saves a Wait() for the path where it doesn't change. We could benchmark this, but microbenchmarks may not be representative of real workloads, and the real-world savings is probably irrelevant, since resolver updates don't happen very frequently in practice. WDYT?

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewable status: 6 of 9 files reviewed, 1 unresolved discussion (waiting on @dfawley and @menghanl)


clientconn.go, line 647 at r2 (raw file):

Previously, dfawley (Doug Fawley) wrote…

Done for the first one.

It's unclear whether the second suggestion is worth doing. It requires an extra atomic read for every call, but saves a Wait() for the path where it doesn't change. We could benchmark this, but microbenchmarks may not be representative of real workloads, and the real-world savings is probably irrelevant, since resolver updates don't happen very frequently in practice. WDYT?

I was thinking that when we do cluster ref-counting, deleting a cluster would result in a update with different balancer config, but the same config selector.
The clusters could be removed one by one when the qps is high, and this will cause multiple unnecessary ConfigSelector updates

@dfawley
Copy link
Member Author

dfawley commented Oct 30, 2020

I was thinking that when we do cluster ref-counting, deleting a cluster would result in a update with different balancer config, but the same config selector.
The clusters could be removed one by one when the qps is high, and this will cause multiple unnecessary ConfigSelector updates

I'm not convinced. The number of updates here should be tiny and the impact on the system as a whole for each operation would also be quite small. Let's save this as a potential future optimization?


// RPCInfo contains RPC information needed by a ConfigSelector.
type RPCInfo struct {
Context context.Context // Contains headers, application timeout
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to move this context out of here and instead make it the first parameter to SelectConfig?

Copy link
Member Author

Choose a reason for hiding this comment

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

I really don't want to do that, as the config selector is not supposed to be blocking and having a Context parameter makes it look like it is fine to block. Context is only passed here for the data it contains (metadata & RPC deadline primarily). This is now awkward because gRPC-Go's API used context inappropriately, but it's better to pass it in a struct than as the first parameter to avoid assumptions about what it means IMO.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with the blocking aspect. But my concern is the same as that in the other comment, that this context might become a dumping ground for stuff. And for someone reading this part of the code, it is not super clear what exact things are passed in this context. They would have to go look at the usages of this context field.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is the user's context for the RPC. So it has whatever the user put in there, of which gRPC only cares about deadline and metadata (unless I'm forgetting something). I wouldn't advocate adding anything else there; we'd use CallOptions instead (what should have been used for metadata and deadline anyway so we wouldn't need to pass this). If we pull out the metadata and pass it instead, then we would be wasting resources (allocations & copies) for something that isn't used by the default config selector (service config).

Also, this is an internal API, so I think we get away with taking some liberties here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a comment to explain the rationale. Thanks.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

internal/resolver/config_selector.go Show resolved Hide resolved
@dfawley dfawley closed this Nov 4, 2020
@dfawley dfawley reopened this Nov 4, 2020
Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 1 of 5 files at r2, 1 of 1 files at r3.
Reviewable status: 8 of 9 files reviewed, 3 unresolved discussions (waiting on @dfawley and @menghanl)


internal/resolver/safe_config_selector_test.go, line 64 at r3 (raw file):

		selectConfig: func(r RPCInfo) *RPCConfig {
			cs1Called <- struct{}{}
			if !reflect.DeepEqual(r, testRPCInfo) {

Nit: Use https://godoc.org/github.com/google/go-cmp/cmp#Diff for the diff

@menghanl menghanl assigned easwars and unassigned menghanl Nov 5, 2020
Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: 7 of 9 files reviewed, 2 unresolved discussions (waiting on @dfawley, @easwars, and @menghanl)


internal/resolver/safe_config_selector_test.go, line 64 at r3 (raw file):

Previously, menghanl (Menghan Li) wrote…

Nit: Use https://godoc.org/github.com/google/go-cmp/cmp#Diff for the diff

Done

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

LGTM

return f.selectConfig(r)
}

func (s) TestSafeConfigSelector(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test is not very easy to read. Lots of goroutines, lots of different time values which are used for waiting/sleeping. Could this be simplified?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure..this test is intended to stress concurrency, since that's the whole point of the type. If you have suggestions for easier ways to cover the same things, then I can redo it.

Basically I want to cover:

  1. cs1 used until a second UpdateConfigSelector call
  2. cs2 used sometime after UpdateConfigSelector is called
  3. UpdateConfigSelector blocks until no cs1 calls are in-flight
  4. cs1 never called after first call to cs2
  5. Return value of SelectConfig matches proper config selector's return value

I could make separate test cases for these, but my worry is that it would end up being 3+x longer because setting up (4) would require most of the same code as (1)-(3).

Copy link
Contributor

Choose a reason for hiding this comment

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

It does look like a lot to cover in a test. Maybe its just me who finds it hard to read this test :)

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
select {
case sendConfigChan <- tc.config:
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to add an unnecessary coupling between test N and test N-1. Could this be avoided by making sure the expected state is reached at the end of test N-1?

Copy link
Member Author

Choose a reason for hiding this comment

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

We do test the expected state at the end of the previous test. Not the state of this channel, but it would be extremely surprising if the test case passes without consuming the config from the channel! This check is here mainly to avoid a hang in the event of some kind of weird bug that I can't actually even imagine. I could just delete the default case, I guess. But it's always good to fail quickly rather than hang.

Another option would be to recreate the client or update the config selector for every test case - then we wouldn't need a channel. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

Another option would be to recreate the client or update the config selector for every test case - then we wouldn't need a channel. WDYT?

Yes, I think that would be better.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done. Getting rid of the channels is nicer.

t.Fatalf("no context received")
}

if want := "/grpc.testing.TestService/EmptyCall"; gotInfo.Method != want {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we move these two checks to inside of the select case in line 145? I feel grouping this with the code where we read gotInfo would make it easier to follow whats happening in the test.

Copy link
Member Author

Choose a reason for hiding this comment

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

Putting it inside the case increases the indent, which I don't like. Similar to above, the default in that select is only there for paranoia.

Actually, let me take advantage of our handy dandy channel wrappers here.

t.Errorf("gotInfo.Method = %q; want %q", gotInfo.Method, want)
}

if gotMD, _ := metadata.FromOutgoingContext(gotInfo.Context); !reflect.DeepEqual(tc.md, gotMD) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this reflect.DeepEqual be avoided?

Copy link
Member Author

Choose a reason for hiding this comment

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

As in, you would prefer cmp.Diff? Done.

Copy link
Contributor

Choose a reason for hiding this comment

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

cmp.Equal would do.

Copy link
Member Author

Choose a reason for hiding this comment

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

The diffs help understanding the output I believe.

}

deadlineSent, _ := ctx.Deadline()
if tc.config != nil && tc.config.Context != nil {
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 lot of special casing around config != nil and the corresponding context != nil. Could you split out the tests where these are expected to be nil and have helper functions for shared code between the tests?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added wantMD and wantDeadline/wantTimeout instead. PTAL.

deadlineSent = time.Now().Add(*tc.config.MethodConfig.Timeout)
}
deadlineGot, _ := gotContext.Deadline()
if diff := deadlineGot.Sub(deadlineSent); diff > time.Second || diff < -time.Second {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we check if the deadline is within this window?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because the deadline is not precise when it is determined as a timeout (from "now", where "now" is not precisely controllable or knowable).

@easwars easwars assigned dfawley and unassigned easwars Nov 9, 2020
cs1 := &fakeConfigSelector{
selectConfig: func(r RPCInfo) *RPCConfig {
cs1Called <- struct{}{}
if diff := cmp.Diff(r, testRPCInfo); diff != "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be better to use cmp.Equal instead of cmp.Diff here. I find the latter to be useful when comparing structured string output where a diff is very useful.

Copy link
Member Author

Choose a reason for hiding this comment

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

Here I think the structs probably benefit from the diff.

internal/resolver/safe_config_selector_appengine.go Outdated Show resolved Hide resolved
return f.selectConfig(r)
}

func (s) TestSafeConfigSelector(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It does look like a lot to cover in a test. Maybe its just me who finds it hard to read this test :)

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
select {
case sendConfigChan <- tc.config:
Copy link
Contributor

Choose a reason for hiding this comment

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

Another option would be to recreate the client or update the config selector for every test case - then we wouldn't need a channel. WDYT?

Yes, I think that would be better.

t.Errorf("gotInfo.Method = %q; want %q", gotInfo.Method, want)
}

if gotMD, _ := metadata.FromOutgoingContext(gotInfo.Context); !reflect.DeepEqual(tc.md, gotMD) {
Copy link
Contributor

Choose a reason for hiding this comment

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

cmp.Equal would do.

}

onCommittedCalled = false
ctx = metadata.NewOutgoingContext(ctx, tc.md)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not ctx := metadata.NewOutgoingContext(ctx, tc.md) by choice?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, that's a mistake. Fixed.

test/resolver_test.go Show resolved Hide resolved
@dfawley
Copy link
Member Author

dfawley commented Nov 11, 2020

PTAL at the recent changes, thanks.

@dfawley dfawley assigned menghanl and easwars and unassigned dfawley Nov 11, 2020
Copy link
Contributor

@easwars easwars left a comment

Choose a reason for hiding this comment

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

LGTM.

clientconn.go Outdated Show resolved Hide resolved
Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 1 of 2 files at r4.
Reviewable status: 5 of 10 files reviewed, 15 unresolved discussions (waiting on @dfawley, @easwars, and @menghanl)


clientconn.go, line 609 at r9 (raw file):

	}
	if cc.dopts.defaultServiceConfig != nil {
		cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{cc})

Does the cc.sc != nil case also need a cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{cc})?


We should probably change cc.applyServiceConfigAndBalancer to

func applyServiceConfigAndBalancerAndConfigSelector(sc, addrs, configSelector)

and call UpdateConfigSelector inside. So we don't have so many places to update safeConfigSelector.

Conceptually, config selector is a subset of method config, so it should be handled in the same place where cc.sc is updated.

And after this change, we will have:
cc.safeConfigSelector.UpdateConfigSelector() is called when

  • service config is updated
  • when resolver.Update contains an error
  • when recv from sc-channel (which nobody likes)

clientconn.go, line 645 at r9 (raw file):

	var ret error
	if cc.dopts.disableServiceConfig || s.ServiceConfig == nil {
		cc.maybeApplyDefaultServiceConfig(s.Addresses)

We are ignoring config selector from the resolver's Update when service config is disabled. Is that right?

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: 5 of 10 files reviewed, 15 unresolved discussions (waiting on @dfawley, @easwars, and @menghanl)


clientconn.go, line 647 at r2 (raw file):

Previously, menghanl (Menghan Li) wrote…

I was thinking that when we do cluster ref-counting, deleting a cluster would result in a update with different balancer config, but the same config selector.
The clusters could be removed one by one when the qps is high, and this will cause multiple unnecessary ConfigSelector updates

(Addressed on github)


clientconn.go, line 609 at r9 (raw file):

Does the cc.sc != nil case also need a cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{cc})?

No, because if we already have a service config, we also already have a config selector that matches it. SC and CS always belong as a pair.

applyServiceConfigAndBalancerAndConfigSelector

Hmm, this is a good idea, and I had that same though. The only problem with this is that when we call this with cc.sc as a parameter, we will also need to be able to indicate to it that the currently-active config selector should continue to be used. But that's hidden inside the SafeConfigSelector. We could pass nil to indicate this? PTAL.


clientconn.go, line 645 at r9 (raw file):

Previously, menghanl (Menghan Li) wrote…

We are ignoring config selector from the resolver's Update when service config is disabled. Is that right?

maybeApplyDefaultServiceConfig also applies the config selector. But yes, CS depends upon SC - conceptually, if there is no service config, there is no config to select.

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 1 of 2 files at r4, 1 of 2 files at r5, 1 of 2 files at r7, 6 of 6 files at r10.
Reviewable status: all files reviewed, 17 unresolved discussions (waiting on @dfawley, @easwars, and @menghanl)


clientconn.go, line 645 at r9 (raw file):

Previously, dfawley (Doug Fawley) wrote…

maybeApplyDefaultServiceConfig also applies the config selector. But yes, CS depends upon SC - conceptually, if there is no service config, there is no config to select.

So disabling service config will disable cluster picking for xDS?


clientconn.go, line 108 at r10 (raw file):

}

type defaultConfigSelector struct {

Nit: staticConfigSelector? constConfigSelector?


internal/resolver/config_selector.go, line 79 at r10 (raw file):

}

func (c *countingConfigSelector) Add() {

Why exported? Is there an interface for WaitGroup?

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewed 5 of 6 files at r11.
Reviewable status: all files reviewed, 16 unresolved discussions (waiting on @dfawley and @easwars)

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Reviewable status: all files reviewed, 16 unresolved discussions (waiting on @dfawley, @easwars, and @menghanl)


clientconn.go, line 645 at r9 (raw file):

Previously, menghanl (Menghan Li) wrote…

So disabling service config will disable cluster picking for xDS?

Disabling service config will disable xDS (no LB policy!)


clientconn.go, line 108 at r10 (raw file):

Previously, menghanl (Menghan Li) wrote…

Nit: staticConfigSelector? constConfigSelector?

Or serviceConfig[Config]Selector? I think I prefer "default" of all these options, personally. Is there any specific reason(s) you don't like it?


internal/resolver/config_selector.go, line 79 at r10 (raw file):

Previously, menghanl (Menghan Li) wrote…

Why exported? Is there an interface for WaitGroup?

I assume this was on Add/Done/Wait before, not UpdateConfigSelector - no, that was just a bad habit. It's been removed.

Copy link
Contributor

@menghanl menghanl left a comment

Choose a reason for hiding this comment

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

Reviewable status: all files reviewed, 14 unresolved discussions (waiting on @dfawley and @easwars)


clientconn.go, line 108 at r10 (raw file):

Previously, dfawley (Doug Fawley) wrote…

Or serviceConfig[Config]Selector? I think I prefer "default" of all these options, personally. Is there any specific reason(s) you don't like it?

I was thinking this struct is not "default". It's just a store for some config that doesn't change.
And now it's used for all configs (when config selector is not set), not just the default.

@dfawley
Copy link
Member Author

dfawley commented Nov 17, 2020

I was thinking this struct is not "default". It's just a store for some config that doesn't change.
And now it's used for all configs (when config selector is not set), not just the default.

I think of this as the "default config selection logic". I.e. it pulls the method config from the service config based on the method name. "static" to me implies that it's some constant configuration (doesn't even vary based on method), which is not the case.

@dfawley dfawley merged commit b88744b into grpc:master Nov 17, 2020
@dfawley dfawley deleted the config_selector branch November 17, 2020 21:22
davidkhala pushed a commit to Hyperledger-TWGC/grpc that referenced this pull request Dec 7, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: Feature New features or improvements in behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants