@@ -31,15 +31,21 @@ var CodedError = status.Errorf
3131
3232var errNilTLS = errors .New ("boulder/grpc: received nil tls.Config" )
3333
34- // checker is an interface for checking the health of a grpc service
35- // implementation.
34+ // checker can be implemented by services to receive health checks via polling.
3635type checker interface {
3736 // Health returns nil if the service is healthy, or an error if it is not.
3837 // If the passed context is canceled, it should return immediately with an
3938 // error.
4039 Health (context.Context ) error
4140}
4241
42+ // onHealthy can be implemented by services to report health to gRPC by callbacks.
43+ type onHealthy interface {
44+ // During server setup, OnHealthy will be passed a callback. The implementation
45+ // should arrange for this callback to be invoked once the service is healthy.
46+ OnHealthy (func ())
47+ }
48+
4349// service represents a single gRPC service that can be registered with a gRPC
4450// server.
4551type service struct {
@@ -214,12 +220,17 @@ func (sb *serverBuilder) Build(tlsConfig *tls.Config, statsRegistry prometheus.R
214220 healthCtx , stopHealthChecks := context .WithCancel (context .Background ())
215221 for _ , s := range sb .services {
216222 check , ok := s .impl .(checker )
217- if ! ok {
218- continue
223+ if ok {
224+ sb . initLongRunningCheck ( healthCtx , s . desc . ServiceName , check . Health )
219225 }
220- sb .initLongRunningCheck (healthCtx , s .desc .ServiceName , check .Health )
221- }
222226
227+ registerReady , ok := s .impl .(onHealthy )
228+ if ok {
229+ registerReady .OnHealthy (func () {
230+ sb .healthSrv .SetServingStatus (s .desc .ServiceName , healthpb .HealthCheckResponse_SERVING )
231+ })
232+ }
233+ }
223234 // Start a goroutine which listens for a termination signal, and then
224235 // gracefully stops the gRPC server. This in turn causes the start() function
225236 // to exit, allowing its caller (generally a main() function) to exit.
0 commit comments