package health
import (
)
func () {
producerBuilderSingleton = &producerBuilder{}
internal.RegisterClientHealthCheckListener = registerClientSideHealthCheckListener
}
type producerBuilder struct{}
var producerBuilderSingleton *producerBuilder
func (*producerBuilder) ( any) (balancer.Producer, func()) {
:= &healthServiceProducer{
cc: .(grpc.ClientConnInterface),
cancel: func() {},
}
return , func() {
.mu.Lock()
defer .mu.Unlock()
.cancel()
}
}
type healthServiceProducer struct {
cc grpc.ClientConnInterface
mu sync.Mutex
cancel func()
}
func ( context.Context, balancer.SubConn, string, func(balancer.SubConnState)) func() {
, := .GetOrBuildProducer(producerBuilderSingleton)
:= .(*healthServiceProducer)
.mu.Lock()
defer .mu.Unlock()
.cancel()
if == nil {
return
}
, := context.WithCancel()
.cancel =
go .startHealthCheck(, , , )
return
}
func ( *healthServiceProducer) ( context.Context, balancer.SubConn, string, func(balancer.SubConnState)) {
:= func( string) (any, error) {
return .cc.NewStream(, &grpc.StreamDesc{ServerStreams: true}, )
}
:= func( connectivity.State, error) {
(balancer.SubConnState{
ConnectivityState: ,
ConnectionError: ,
})
}
:= internal.HealthCheckFunc(, , , )
if == nil {
return
}
if status.Code() == codes.Unimplemented {
logger.Errorf("Subchannel health check is unimplemented at server side, thus health check is disabled for SubConn %p", )
} else {
logger.Errorf("Health checking failed for SubConn %p: %v", , )
}
}