@@ -32,6 +32,7 @@ import (
3232 "google.golang.org/grpc/balancer"
3333 "google.golang.org/grpc/connectivity"
3434 "google.golang.org/grpc/internal"
35+ "google.golang.org/grpc/internal/balancer/gracefulswitch"
3536 "google.golang.org/grpc/internal/buffer"
3637 "google.golang.org/grpc/internal/grpclog"
3738 "google.golang.org/grpc/internal/grpcsync"
@@ -69,6 +70,7 @@ func (bb) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balancer.Ba
6970 requestCountMax : defaultRequestCountMax ,
7071 }
7172 b .logger = prefixLogger (b )
73+ b .child = gracefulswitch .NewBalancer (b , bOpts )
7274 go b .run ()
7375 b .logger .Infof ("Created" )
7476 return b
@@ -102,7 +104,7 @@ type clusterImplBalancer struct {
102104 xdsClient xdsclient.XDSClient
103105
104106 config * LBConfig
105- childLB balancer .Balancer
107+ child * gracefulswitch .Balancer
106108 cancelLoadReport func ()
107109 edsServiceName string
108110 lrsServer * bootstrap.ServerConfig
@@ -251,31 +253,19 @@ func (b *clusterImplBalancer) UpdateClientConnState(s balancer.ClientConnState)
251253 return err
252254 }
253255
254- // If child policy is a different type, recreate the sub-balancer.
255256 if b .config == nil || b .config .ChildPolicy .Name != newConfig .ChildPolicy .Name {
256- if b . childLB != nil {
257- b . childLB . Close ( )
257+ if err := b . child . SwitchTo ( bb ); err != nil {
258+ return fmt . Errorf ( "error switching to child of type %q: %v" , newConfig . ChildPolicy . Name , err )
258259 }
259- b .childLB = bb .Build (b , b .bOpts )
260260 }
261261 b .config = newConfig
262262
263- if b .childLB == nil {
264- // This is not an expected situation, and should be super rare in
265- // practice.
266- //
267- // When this happens, we already applied all the other configurations
268- // (drop/circuit breaking), but there's no child policy. This balancer
269- // will be stuck, and we report the error to the parent.
270- return fmt .Errorf ("child policy is nil, this means balancer %q's Build() returned nil" , newConfig .ChildPolicy .Name )
271- }
272-
273263 // Notify run() of this new config, in case drop and request counter need
274264 // update (which means a new picker needs to be generated).
275265 b .pickerUpdateCh .Put (newConfig )
276266
277267 // Addresses and sub-balancer config are sent to sub-balancer.
278- return b .childLB .UpdateClientConnState (balancer.ClientConnState {
268+ return b .child .UpdateClientConnState (balancer.ClientConnState {
279269 ResolverState : s .ResolverState ,
280270 BalancerConfig : b .config .ChildPolicy .Config ,
281271 })
@@ -286,10 +276,7 @@ func (b *clusterImplBalancer) ResolverError(err error) {
286276 b .logger .Warningf ("xds: received resolver error {%+v} after clusterImplBalancer was closed" , err )
287277 return
288278 }
289-
290- if b .childLB != nil {
291- b .childLB .ResolverError (err )
292- }
279+ b .child .ResolverError (err )
293280}
294281
295282func (b * clusterImplBalancer ) UpdateSubConnState (sc balancer.SubConn , s balancer.SubConnState ) {
@@ -318,39 +305,23 @@ func (b *clusterImplBalancer) UpdateSubConnState(sc balancer.SubConn, s balancer
318305 }
319306 }
320307 b .scWrappersMu .Unlock ()
321- if b .childLB != nil {
322- b .childLB .UpdateSubConnState (sc , s )
323- }
308+ b .child .UpdateSubConnState (sc , s )
324309}
325310
326311func (b * clusterImplBalancer ) Close () {
327312 b .mu .Lock ()
328313 b .closed .Fire ()
329314 b .mu .Unlock ()
330315
331- if b .childLB != nil {
332- b .childLB .Close ()
333- b .childLB = nil
334- b .childState = balancer.State {}
335- }
316+ b .child .Close ()
317+ b .childState = balancer.State {}
336318 b .pickerUpdateCh .Close ()
337319 <- b .done .Done ()
338320 b .logger .Infof ("Shutdown" )
339321}
340322
341323func (b * clusterImplBalancer ) ExitIdle () {
342- if b .childLB == nil {
343- return
344- }
345- if ei , ok := b .childLB .(balancer.ExitIdler ); ok {
346- ei .ExitIdle ()
347- return
348- }
349- // Fallback for children that don't support ExitIdle -- connect to all
350- // SubConns.
351- for _ , sc := range b .scWrappers {
352- sc .Connect ()
353- }
324+ b .child .ExitIdle ()
354325}
355326
356327// Override methods to accept updates from the child LB.
0 commit comments