Skip to content

Commit f5a92b6

Browse files
committed
tetra: use the builtin gRPC retry backoff mechanism
gRGC A6 - gRPC Retry Design (a.k.a. built in backoff retry) https://github.com/grpc/proposal/blob/master/A6-client-retries.md was implemented by grpc/grpc-go#2111 but unusable for a long time since maxAttempts was limited to hardcoded 5 (grpc/grpc-go#4615), recent PR fixed that grpc/grpc-go#7229. It's transparent to the user, to see it in action, make sure the gRPC server is unreachable (do not start tetragon for example), run tetra with: GRPC_GO_LOG_SEVERITY_LEVEL=warning <tetra cmd> Note that logs don't always have the time to be pushed before exit so output might be a bit off but the number of retries is respected (you can debug or synchronously print in the grpc/stream.c:shouldRetry or :withRetry to verify). Also note that the final backoff duration is completely random and chosen between 0 and the final duration that was computed via to the params: https://github.com/grpc/grpc-go/blob/v1.65.0/stream.go#L702 Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
1 parent d9cca23 commit f5a92b6

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

cmd/tetra/common/client.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,47 @@ import (
1515
"google.golang.org/grpc/credentials/insecure"
1616
)
1717

18+
// gRGC A6 - gRPC Retry Design (a.k.a. built in backoff retry)
19+
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md
20+
// was implemented by https://github.com/grpc/grpc-go/pull/2111 but unusable
21+
// for a long time since maxAttempts was limited to hardcoded 5
22+
// (https://github.com/grpc/grpc-go/issues/4615), recent PR fixed that
23+
// https://github.com/grpc/grpc-go/pull/7229.
24+
//
25+
// It's transparent to the user, to see it in action, make sure the gRPC server
26+
// is unreachable (do not start tetragon for example), run tetra with:
27+
// GRPC_GO_LOG_SEVERITY_LEVEL=warning <tetra cmd>
28+
//
29+
// Note that logs don't always have the time to be pushed before exit so output
30+
// might be a bit off but the number of retries is respected (you can debug or
31+
// synchronously print in the grpc/stream.c:shouldRetry or :withRetry to
32+
// verify).
33+
//
34+
// Also note that the final backoff duration is completely random and chosen
35+
// between 0 and the final duration that was computed via to the params:
36+
// https://github.com/grpc/grpc-go/blob/v1.65.0/stream.go#L702
37+
func retryPolicy(retries int) string {
38+
if retries < 0 {
39+
// gRPC should ignore the invalid retry policy but will issue a warning,
40+
return "{}"
41+
}
42+
// maxAttempt includes the first call
43+
maxAttempt := retries + 1
44+
// let's not limit backoff by hardcoding 1h in MaxBackoff
45+
// since we need to provide a value >0
46+
return fmt.Sprintf(`{
47+
"methodConfig": [{
48+
"name": [{"service": "tetragon.FineGuidanceSensors"}],
49+
"retryPolicy": {
50+
"MaxAttempts": %d,
51+
"InitialBackoff": "1s",
52+
"MaxBackoff": "3600s",
53+
"BackoffMultiplier": 2,
54+
"RetryableStatusCodes": [ "UNAVAILABLE" ]
55+
}
56+
}]}`, maxAttempt)
57+
}
58+
1859
func CliRunErr(fn func(ctx context.Context, cli tetragon.FineGuidanceSensorsClient), fnErr func(err error)) {
1960
c, err := NewClientWithDefaultContextAndAddress()
2061
if err != nil {
@@ -60,7 +101,11 @@ func NewClient(ctx context.Context, address string, timeout time.Duration) (*Cli
60101
c.Ctx, _ = signal.NotifyContext(timeoutContext, syscall.SIGINT, syscall.SIGTERM)
61102

62103
var err error
63-
c.conn, err = grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
104+
c.conn, err = grpc.NewClient(address,
105+
grpc.WithTransportCredentials(insecure.NewCredentials()),
106+
grpc.WithDefaultServiceConfig(retryPolicy(Retries)),
107+
grpc.WithMaxCallAttempts(Retries+1), // maxAttempt includes the first call
108+
)
64109
if err != nil {
65110
return nil, fmt.Errorf("failed to create gRPC client with address %s: %w", address, err)
66111
}

0 commit comments

Comments
 (0)