I am having the following code:
dialCtx, cancel := context.WithTimeout(ctx, 120*time.Second)
defer cancel()
conn, err := grpc.DialContext(dialCtx, address,
grpc.WithTransportCredentials(creds),
grpc.WithKeepaliveParams(keepAlive),
grpc.WithBlock(),
)
if err != nil {
return fmt.Errorf("failed to connect to server: %v", err)
}
I am trying to create a connection with gRPC server. One important thing is that I am using WithBlock()
which blocks the dial until the connection is ready or the context timeouts. Okay, but when the context timeouts, I don't get what was the connection problem, aka last connection error. I get context deadline exceeded
.
I tried following:
grpc.FailOnNonTempDialError(true)
- error is returned when service is not available, but when TLS verification fails, re-connection continues.grpc.WithContextDialer(...)
- does not work for me, because sometimes the initial dialling is successful, but if server certificates validation fails, whole connection is closed.How can I get that last connection error?
After some more research, I decided to update the grpc package version. I was using v1.27.0 and the latest is v1.35.0. Between these version, the problem was fixed and a new dial option introduced:
grpc.WithReturnConnectionError()
It's a way better now, but there is room for improvement. Currently, lastError and the context error are combined like that:
conn, err = nil, fmt.Errorf("%v: %v", ctx.Err(), err)
The problem is that the underlying error's type is lost, so the only way to make some action, based on the error, is string comparing(which is not reliable).
I hope that answer will be useful.