@@ -34,6 +34,7 @@ import (
34
34
"google.golang.org/grpc/codes"
35
35
"google.golang.org/grpc/connectivity"
36
36
"google.golang.org/grpc/credentials"
37
+ "google.golang.org/grpc/internal"
37
38
"google.golang.org/grpc/internal/backoff"
38
39
"google.golang.org/grpc/internal/channelz"
39
40
"google.golang.org/grpc/internal/grpcsync"
@@ -136,7 +137,6 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires
136
137
func DialContext (ctx context.Context , target string , opts ... DialOption ) (conn * ClientConn , err error ) {
137
138
cc := & ClientConn {
138
139
target : target ,
139
- csMgr : & connectivityStateManager {},
140
140
conns : make (map [* addrConn ]struct {}),
141
141
dopts : defaultDialOptions (),
142
142
czData : new (channelzData ),
@@ -189,6 +189,8 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
189
189
// Register ClientConn with channelz.
190
190
cc .channelzRegistration (target )
191
191
192
+ cc .csMgr = newConnectivityStateManager (cc .channelzID )
193
+
192
194
if err := cc .validateTransportCredentials (); err != nil {
193
195
return nil , err
194
196
}
@@ -473,7 +475,6 @@ func (cc *ClientConn) validateTransportCredentials() error {
473
475
func (cc * ClientConn ) channelzRegistration (target string ) {
474
476
cc .channelzID = channelz .RegisterChannel (& channelzChannel {cc }, cc .dopts .channelzParentID , target )
475
477
cc .addTraceEvent ("created" )
476
- cc .csMgr .channelzID = cc .channelzID
477
478
}
478
479
479
480
// chainUnaryClientInterceptors chains all unary client interceptors into one.
@@ -538,13 +539,27 @@ func getChainStreamer(interceptors []StreamClientInterceptor, curr int, finalStr
538
539
}
539
540
}
540
541
542
+ // newConnectivityStateManager creates an connectivityStateManager with
543
+ // the specified id.
544
+ func newConnectivityStateManager (id * channelz.Identifier ) * connectivityStateManager {
545
+ return & connectivityStateManager {
546
+ channelzID : id ,
547
+ pubSub : grpcsync .NewPubSub (),
548
+ }
549
+ }
550
+
541
551
// connectivityStateManager keeps the connectivity.State of ClientConn.
542
552
// This struct will eventually be exported so the balancers can access it.
553
+ //
554
+ // TODO: If possible, get rid of the `connectivityStateManager` type, and
555
+ // provide this functionality using the `PubSub`, to avoid keeping track of
556
+ // the connectivity state at two places.
543
557
type connectivityStateManager struct {
544
558
mu sync.Mutex
545
559
state connectivity.State
546
560
notifyChan chan struct {}
547
561
channelzID * channelz.Identifier
562
+ pubSub * grpcsync.PubSub
548
563
}
549
564
550
565
// updateState updates the connectivity.State of ClientConn.
@@ -560,6 +575,8 @@ func (csm *connectivityStateManager) updateState(state connectivity.State) {
560
575
return
561
576
}
562
577
csm .state = state
578
+ csm .pubSub .Publish (state )
579
+
563
580
channelz .Infof (logger , csm .channelzID , "Channel Connectivity change to %v" , state )
564
581
if csm .notifyChan != nil {
565
582
// There are other goroutines waiting on this channel.
@@ -583,6 +600,10 @@ func (csm *connectivityStateManager) getNotifyChan() <-chan struct{} {
583
600
return csm .notifyChan
584
601
}
585
602
603
+ func (csm * connectivityStateManager ) close () {
604
+ csm .pubSub .Stop ()
605
+ }
606
+
586
607
// ClientConnInterface defines the functions clients need to perform unary and
587
608
// streaming RPCs. It is implemented by *ClientConn, and is only intended to
588
609
// be referenced by generated code.
@@ -771,6 +792,10 @@ func init() {
771
792
panic (fmt .Sprintf ("impossible error parsing empty service config: %v" , cfg .Err ))
772
793
}
773
794
emptyServiceConfig = cfg .Config .(* ServiceConfig )
795
+
796
+ internal .SubscribeToConnectivityStateChanges = func (cc * ClientConn , s grpcsync.Subscriber ) func () {
797
+ return cc .csMgr .pubSub .Subscribe (s )
798
+ }
774
799
}
775
800
776
801
func (cc * ClientConn ) maybeApplyDefaultServiceConfig (addrs []resolver.Address ) {
@@ -1224,6 +1249,7 @@ func (cc *ClientConn) Close() error {
1224
1249
conns := cc .conns
1225
1250
cc .conns = nil
1226
1251
cc .csMgr .updateState (connectivity .Shutdown )
1252
+ cc .csMgr .close ()
1227
1253
1228
1254
pWrapper := cc .blockingpicker
1229
1255
rWrapper := cc .resolverWrapper
0 commit comments