-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
internal/grpcsync: support two ways to schedule a callback with the serializer #7408
Conversation
556f171
to
290191e
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #7408 +/- ##
==========================================
- Coverage 81.45% 81.38% -0.08%
==========================================
Files 348 350 +2
Lines 26752 26845 +93
==========================================
+ Hits 21792 21848 +56
- Misses 3773 3799 +26
- Partials 1187 1198 +11
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM but one minor simplification suggestion. Naming question: Maybe
is OK and what I originally proposed, but how do you feel about TrySchedule
?
balancer_wrapper.go
Outdated
@@ -94,8 +94,8 @@ func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper { | |||
// the underlying balancer. This is always executed from the serializer, so | |||
// it is safe to call into the balancer here. | |||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error { | |||
errCh := make(chan error) | |||
ok := ccb.serializer.Schedule(func(ctx context.Context) { | |||
errCh := make(chan error, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can stay unbounded, and maybe improved a little:
func uCCS() {
errCh := make(chan error)
defer close(errCh)
uccs := ...
onFailure := func() {}
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to block on reading from this channel when the uccs
callback is successfully scheduled on the serializer (because we want to handle state updates inline). But if we don't send something on the channel from the onFailure
func, the last line return <-errCh
will block forever, right? This is equivalent, isn't it? https://go.dev/play/p/GHPD4MLhis6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Um, yes, I tried to simplify too much, oops. You can still make the channel unbuffered (sorry for saying "unbounded"), and not defer the close but call close in the onFailure:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -309,8 +309,8 @@ func (b *cdsBalancer) UpdateClientConnState(state balancer.ClientConnState) erro | |||
b.lbCfg = lbCfg | |||
|
|||
// Handle the update in a blocking fashion. | |||
done := make(chan struct{}) | |||
ok = b.serializer.Schedule(func(context.Context) { | |||
errCh := make(chan error, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar here as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't make it unbuffered here because if ScheduleOr
fails, it will call onFailure
inline and this means that the write to the channel on line 327 errCh <- errBalancerClosed
will happen before the read on line 330. Therefore it will just hang.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, that makes sense.
The earlier API to add callbacks to the serializer,
Schedule
, was returning abool
to indicate whether or not the callback was added to the serializer. This had the following problems:Schedule
fails, while for most of the others, it is totally OK for the call toSchedule
to fail.This PR splits the API into two:
MaybeSchedule
: A best effort API that fails silently if the serializer is closedScheduleOr
: An API which runs anonFailure
func if the callback cannot be scheduledRELEASE NOTES: none