forked from improbable-eng/grpc-web
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhealth.go
65 lines (56 loc) · 1.93 KB
/
health.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package grpcweb
import (
"context"
"time"
backoff "github.com/cenkalti/backoff/v4"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/status"
)
const healthCheckMethod = "/grpc.health.v1.Health/Watch"
// Client health check function is also part of the grpc/internal package
// The following code is a simplified version of client.go
// For more details see: https://pkg.go.dev/google.golang.org/grpc/health
func ClientHealthCheck(ctx context.Context, backendConn *grpc.ClientConn, service string, setServingStatus func(serving bool)) error {
shouldBackoff := false // No need for backoff on the first connection attempt
backoffSrc := backoff.NewExponentialBackOff()
healthClient := healthpb.NewHealthClient(backendConn)
for {
// Backs off if the connection has failed in some way without receiving a message in the previous retry.
if shouldBackoff {
select {
case <-time.After(backoffSrc.NextBackOff()):
case <-ctx.Done():
return nil
}
}
shouldBackoff = true // we should backoff next time, since we attempt connecting below
req := healthpb.HealthCheckRequest{Service: service}
s, err := healthClient.Watch(ctx, &req)
if err != nil {
continue
}
resp := new(healthpb.HealthCheckResponse)
for {
err = s.RecvMsg(resp)
if err != nil {
setServingStatus(false)
// The health check functionality should be disabled if health check service is not implemented on the backend
if status.Code(err) == codes.Unimplemented {
return err
}
// breaking out of the loop, since we got an error from Recv, triggering reconnect
break
}
// As a message has been received, removes the need for backoff for the next retry.
shouldBackoff = false
backoffSrc.Reset()
if resp.Status == healthpb.HealthCheckResponse_SERVING {
setServingStatus(true)
} else {
setServingStatus(false)
}
}
}
}