@@ -48,6 +48,7 @@ import (
4848 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
4949 "golang.org/x/mod/sumdb/note"
5050 "google.golang.org/api/option"
51+ "google.golang.org/grpc"
5152)
5253
5354func init () {
@@ -120,6 +121,25 @@ var (
120121 imageName = flag .String ("image_name" , "" , "Name of the cached docker image. Only used to decorate slog events." )
121122)
122123
124+ // grpcServiceConfig is a gRPC service config in JSON format which explicitly specifies hedging for GCS ReadObject calls.
125+ const grpcServiceConfig = `{
126+ "methodConfig": [
127+ {
128+ "name": [
129+ {
130+ "service": "google.storage.v2.Storage",
131+ "method": "ReadObject"
132+ }
133+ ],
134+ "hedgingPolicy": {
135+ "maxAttempts": 3,
136+ "hedgingDelay": "0.08s",
137+ "nonFatalStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"]
138+ }
139+ }
140+ ]
141+ }`
142+
123143// nolint:staticcheck
124144func main () {
125145 flag .Parse ()
@@ -145,7 +165,10 @@ func main() {
145165 Timeout : * clientHTTPTimeout ,
146166 }
147167
148- gcsClient , err := gcs .NewGRPCClient (ctx , option .WithGRPCConnectionPool (* gcsConnections ))
168+ gcsClient , err := gcs .NewGRPCClient (ctx ,
169+ option .WithGRPCConnectionPool (* gcsConnections ),
170+ option .WithGRPCDialOption (grpc .WithDefaultServiceConfig (grpcServiceConfig )),
171+ )
149172 if err != nil {
150173 fatal (ctx , "Failed to create gRPC GCS client" , slog .Any ("error" , err ))
151174 }
0 commit comments