Skip to content

Commit

Permalink
client: add WithResolvers options for specifying client-local resolve…
Browse files Browse the repository at this point in the history
…rs (#3320)
  • Loading branch information
dfawley authored Jan 14, 2020
1 parent e8a4440 commit 0083f6e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
13 changes: 11 additions & 2 deletions clientconn.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
// Only try to parse target when resolver builder is not already set.
cc.parsedTarget = parseTarget(cc.target)
grpclog.Infof("parsed scheme: %q", cc.parsedTarget.Scheme)
cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
cc.dopts.resolverBuilder = cc.getResolver(cc.parsedTarget.Scheme)
if cc.dopts.resolverBuilder == nil {
// If resolver builder is still nil, the parsed target's scheme is
// not registered. Fallback to default resolver and set Endpoint to
Expand All @@ -253,7 +253,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
Scheme: resolver.GetDefaultScheme(),
Endpoint: target,
}
cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
cc.dopts.resolverBuilder = cc.getResolver(cc.parsedTarget.Scheme)
}
} else {
cc.parsedTarget = resolver.Target{Endpoint: target}
Expand Down Expand Up @@ -1542,3 +1542,12 @@ func (c *channelzChannel) ChannelzMetric() *channelz.ChannelInternalMetric {
// Deprecated: This error is never returned by grpc and should not be
// referenced by users.
var ErrClientConnTimeout = errors.New("grpc: timed out when dialing")

func (cc *ClientConn) getResolver(scheme string) resolver.Builder {
for _, rb := range cc.dopts.resolvers {
if cc.parsedTarget.Scheme == rb.Scheme() {
return rb
}
}
return resolver.Get(cc.parsedTarget.Scheme)
}
4 changes: 2 additions & 2 deletions clientconn_state_transition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (s) TestStateTransitions_TriesAllAddrsBeforeTransientFailure(t *testing.T)
{Addr: lis1.Addr().String()},
{Addr: lis2.Addr().String()},
}})
client, err := DialContext(ctx, "this-gets-overwritten", WithInsecure(), WithBalancerName(stateRecordingBalancerName), withResolverBuilder(rb))
client, err := DialContext(ctx, "whatever:///this-gets-overwritten", WithInsecure(), WithBalancerName(stateRecordingBalancerName), WithResolvers(rb))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -414,7 +414,7 @@ func (s) TestStateTransitions_MultipleAddrsEntersReady(t *testing.T) {
{Addr: lis1.Addr().String()},
{Addr: lis2.Addr().String()},
}})
client, err := DialContext(ctx, "this-gets-overwritten", WithInsecure(), WithBalancerName(stateRecordingBalancerName), withResolverBuilder(rb))
client, err := DialContext(ctx, "whatever:///this-gets-overwritten", WithInsecure(), WithBalancerName(stateRecordingBalancerName), WithResolvers(rb))
if err != nil {
t.Fatal(err)
}
Expand Down
8 changes: 4 additions & 4 deletions clientconn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,10 +539,10 @@ func (s) TestDial_OneBackoffPerRetryGroup(t *testing.T) {
{Addr: lis1.Addr().String()},
{Addr: lis2.Addr().String()},
}})
client, err := DialContext(ctx, "this-gets-overwritten",
client, err := DialContext(ctx, "whatever:///this-gets-overwritten",
WithInsecure(),
WithBalancerName(stateRecordingBalancerName),
withResolverBuilder(rb),
WithResolvers(rb),
withMinConnectDeadline(getMinConnectTimeout))
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -1085,9 +1085,9 @@ func (s) TestUpdateAddresses_RetryFromFirstAddr(t *testing.T) {
rb := manual.NewBuilderWithScheme("whatever")
rb.InitialState(resolver.State{Addresses: addrsList})

client, err := Dial("this-gets-overwritten",
client, err := Dial("whatever:///this-gets-overwritten",
WithInsecure(),
withResolverBuilder(rb),
WithResolvers(rb),
withBackoff(noBackoff{}),
WithBalancerName(stateRecordingBalancerName),
withMinConnectDeadline(func() time.Duration { return time.Hour }))
Expand Down
13 changes: 13 additions & 0 deletions dialoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type dialOptions struct {
// resolver.ResolveNow(). The user will have no need to configure this, but
// we need to be able to configure this in tests.
resolveNowBackoff func(int) time.Duration
resolvers []resolver.Builder
}

// DialOption configures how we set up the connection.
Expand Down Expand Up @@ -589,3 +590,15 @@ func withResolveNowBackoff(f func(int) time.Duration) DialOption {
o.resolveNowBackoff = f
})
}

// WithResolvers allows a list of resolver implementations to be registered
// locally with the ClientConn without needing to be globally registered via
// resolver.Register. They will be matched against the scheme used for the
// current Dial only, and will take precedence over the global registry.
//
// This API is EXPERIMENTAL.
func WithResolvers(rs ...resolver.Builder) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.resolvers = rs
})
}

0 comments on commit 0083f6e

Please sign in to comment.