@@ -277,10 +277,17 @@ type healthData struct {
277277 // to the LB policy. This is stored to avoid sending updates when the
278278 // SubConn has already exited connectivity state READY.
279279 connectivityState connectivity.State
280+ // closeHealthProducer stores function to close the ref counted health
281+ // producer. The health producer is automatically closed when the SubConn
282+ // state changes.
283+ closeHealthProducer func ()
280284}
281285
282286func newHealthData (s connectivity.State ) * healthData {
283- return & healthData {connectivityState : s }
287+ return & healthData {
288+ connectivityState : s ,
289+ closeHealthProducer : func () {},
290+ }
284291}
285292
286293// updateState is invoked by grpc to push a subConn state update to the
@@ -420,10 +427,11 @@ func (acbw *acBalancerWrapper) closeProducers() {
420427// Notice: This type is EXPERIMENTAL and may be changed or removed in a
421428// later release.
422429type HealthCheckOptions struct {
423- // Name of the gRPC service running on the server for reporting health state.
424- // If the service name is empty, client side health checking will be disabled.
425- HealthServiceName string
426- Listener func (balancer.SubConnState )
430+ // ServiceName of the gRPC service running on the server for reporting health state.
431+ ServiceName string
432+ // Listener is called when the health update is received from the health
433+ // service running on the server.
434+ Listener func (balancer.SubConnState )
427435}
428436
429437// RegisterHealthListener accepts a health listener from the LB policy. It sends
@@ -434,6 +442,7 @@ type HealthCheckOptions struct {
434442func (acbw * acBalancerWrapper ) RegisterHealthListener (listener func (balancer.SubConnState )) {
435443 acbw .healthMu .Lock ()
436444 defer acbw .healthMu .Unlock ()
445+ acbw .healthData .closeHealthProducer ()
437446 // listeners should not be registered when the connectivity state
438447 // isn't Ready. This may happen when the balancer registers a listener
439448 // after the connectivityState is updated, but before it is notified
@@ -445,14 +454,21 @@ func (acbw *acBalancerWrapper) RegisterHealthListener(listener func(balancer.Sub
445454 // registered health listeners.
446455 hd := newHealthData (connectivity .Ready )
447456 acbw .healthData = hd
457+ if listener == nil {
458+ return
459+ }
448460
449461 // Client side health checking is enabled when all the following
450462 // conditions are satisfied:
451- // 1. The health check config is present in the service config.
452- // 2. Health checking is not disabled using the dial option.
453- // 3. The health package is imported.
463+ // 1. Health checking is not disabled using the dial option.
464+ // 2. The health package is imported.
465+ // 3. The health check config is present in the service config.
466+ healthCheckEnabled := ! acbw .ccb .cc .dopts .disableHealthCheck
454467 regHealthLisFn := internal .RegisterClientHealthCheckListener
455- healthCheckEnabled := ! acbw .ccb .cc .dopts .disableHealthCheck && regHealthLisFn != nil
468+ if regHealthLisFn == nil {
469+ // The health package is not imported.
470+ healthCheckEnabled = false
471+ }
456472 var cfg * healthCheckConfig
457473 if healthCheckEnabled {
458474 // Avoid acquiring cc.mu unless necessary.
@@ -467,14 +483,11 @@ func (acbw *acBalancerWrapper) RegisterHealthListener(listener func(balancer.Sub
467483 // Don't send updates if a new listener is registered.
468484 acbw .healthMu .Lock ()
469485 defer acbw .healthMu .Unlock ()
470- curHD := acbw .healthData
471- if curHD != hd {
486+ if acbw .healthData != hd {
472487 return
473488 }
474489 if ! healthCheckEnabled {
475- if listener != nil {
476- listener (balancer.SubConnState {ConnectivityState : connectivity .Ready })
477- }
490+ listener (balancer.SubConnState {ConnectivityState : connectivity .Ready })
478491 return
479492 }
480493 // Serialize the health updates from the health producer with
@@ -485,23 +498,19 @@ func (acbw *acBalancerWrapper) RegisterHealthListener(listener func(balancer.Sub
485498 return
486499 }
487500 acbw .healthMu .Lock ()
488- curHD := acbw .healthData
489- acbw .healthMu .Unlock ()
490- if curHD != hd {
501+ defer acbw .healthMu .Unlock ()
502+ if acbw .healthData != hd {
491503 return
492504 }
493505 listener (scs )
494506 })
495507 }
496508
497- if listener == nil {
498- listenerWrapper = nil
499- }
500-
501509 healthOpts := HealthCheckOptions {
502- HealthServiceName : cfg .ServiceName ,
503- Listener : listenerWrapper ,
510+ ServiceName : cfg .ServiceName ,
511+ Listener : listenerWrapper ,
504512 }
505- regHealthLisFn .(func (context.Context , balancer.SubConn , HealthCheckOptions ))(ctx , acbw , healthOpts )
513+ fn := regHealthLisFn .(func (context.Context , balancer.SubConn , HealthCheckOptions ) func ())
514+ hd .closeHealthProducer = fn (ctx , acbw , healthOpts )
506515 })
507516}
0 commit comments