Skip to content

Commit 2e608b7

Browse files
authored
Merge pull request crossplane#6125 from negz/try-harder
Wait for functions to become ready
2 parents 9967f45 + 5846bcd commit 2e608b7

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

internal/xfn/function_runner.go

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,28 @@ const (
5050
errFmtDialFunction = "cannot gRPC dial target %q from status.endpoint of active FunctionRevision %q"
5151
)
5252

53-
// TODO(negz): Should any of these be configurable?
54-
const (
55-
// This configures a gRPC client to use round robin load balancing. This
56-
// means that if the Function Deployment has more than one Pod, and the
57-
// Function Service is headless, requests will be spread across each Pod.
58-
// See https://github.com/grpc/grpc/blob/v1.58.0/doc/load-balancing.md#load-balancing-policies
59-
lbRoundRobin = `{"loadBalancingConfig":[{"round_robin":{}}]}`
60-
61-
dialFunctionTimeout = 10 * time.Second
62-
runFunctionTimeout = 10 * time.Second
63-
)
53+
// This configures a gRPC client to use round robin load balancing. This means
54+
// that if the Function Deployment has more than one Pod, and the Function
55+
// Service is headless, requests will be spread across each Pod.
56+
// See https://github.com/grpc/grpc/blob/v1.58.0/doc/load-balancing.md#load-balancing-policies
57+
//
58+
// It also configures the gRPC client to wait for the server to be ready before
59+
// sending RPCs. Notably this gives Functions time to start before we make a
60+
// request. See https://grpc.io/docs/guides/wait-for-ready/
61+
const svcConfig = `
62+
{
63+
"loadBalancingConfig": [
64+
{
65+
"round_robin":{}
66+
}
67+
],
68+
"methodConfig": [
69+
{
70+
"name": [{}],
71+
"waitForReady": true
72+
}
73+
]
74+
}`
6475

6576
// A PackagedFunctionRunner runs a Function by making a gRPC call to a Function
6677
// package's runtime. It creates a gRPC client connection for each Function. The
@@ -136,10 +147,6 @@ func (r *PackagedFunctionRunner) RunFunction(ctx context.Context, name string, r
136147
return nil, errors.Wrapf(err, errFmtGetClientConn, name)
137148
}
138149

139-
// This context is used for actually making the request.
140-
ctx, cancel := context.WithTimeout(ctx, runFunctionTimeout)
141-
defer cancel()
142-
143150
rsp, err := NewBetaFallBackFunctionRunnerServiceClient(conn).RunFunction(ctx, req)
144151
return rsp, errors.Wrapf(err, errFmtRunFunction, name)
145152
}
@@ -220,18 +227,14 @@ func (r *PackagedFunctionRunner) getClientConn(ctx context.Context, name string)
220227
delete(r.conns, name)
221228
}
222229

223-
// This context is only used for setting up the connection.
224-
ctx, cancel := context.WithTimeout(ctx, dialFunctionTimeout)
225-
defer cancel()
226-
227230
is := make([]grpc.UnaryClientInterceptor, len(r.interceptors))
228231
for i := range r.interceptors {
229232
is[i] = r.interceptors[i].CreateInterceptor(name, active.Spec.Package)
230233
}
231234

232-
conn, err := grpc.DialContext(ctx, active.Status.Endpoint, //nolint:staticcheck // Figure out how to replace deprecated grpc.DialContext with grpc.NewClient and still pass the dialFunctionTimeout.
235+
conn, err := grpc.NewClient(active.Status.Endpoint,
233236
grpc.WithTransportCredentials(r.creds),
234-
grpc.WithDefaultServiceConfig(lbRoundRobin),
237+
grpc.WithDefaultServiceConfig(svcConfig),
235238
grpc.WithChainUnaryInterceptor(is...))
236239
if err != nil {
237240
return nil, errors.Wrapf(err, errFmtDialFunction, active.Status.Endpoint, active.GetName())

0 commit comments

Comments
 (0)