-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
The current benchmark client uses a Go channel to propagate cancellation information to spawned goroutines. RPCs are sent using context.Background()
(link). Cancellation is checked within goroutines using select
statements with default
cases to poll the channel (link).
This custom channel-based mechanism is not the idiomatic way to handle cancellation in Go. The standard approach, as recommended by Google's Go Style Guides, is to use context.Context
(Go Style Decisions - Contexts).
Here’s the recommended refactoring:
- Pass a Context: The function creating the client (e.g.,
newClient
) should accept acontext.Context
as its first argument. - Propagate the Context: This context should be passed down to all goroutines spawned by the client.
- Use Context in RPCs: Each RPC call should be made with this propagated context, for example:
client.Mth(ctx, req)
. This allows gRPC to handle cancellation and deadlines automatically. - Check for Cancellation: Goroutines can check for cancellation using the context:
- After RPC calls: Check if the error returned by the RPC call corresponds to
status.Canceled
orcontext.Canceled
. - Within long-running tasks: Block until the context is done using
select { case <-ctx.Done(): return ctx.Err() }
. - Non-blocking check: Check if the context has been cancelled using
if ctx.Err() != nil { return ctx.Err() }
.
- After RPC calls: Check if the error returned by the RPC call corresponds to
Adopting context.Context
for cancellation and deadlines aligns the client with Go best practices (How to use a Go context), making the code more understandable and maintainable.
We should ensure this refactoring doesn't adversely effect the benchmark performance. A maintainer can manually run the benchmark before the change is merged.