Skip to content
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

util/singleflight: add DoChanContext #12003

Merged
merged 1 commit into from
Jun 10, 2024
Merged

Conversation

andrew-d
Copy link
Member

@andrew-d andrew-d commented May 4, 2024

This is a variant of DoChan that supports context propagation, such that the context provided to the inner function will only be canceled when there are no more waiters for a given key. This can be used to deduplicate expensive and cancelable calls among multiple callers safely.

Updates #11935

Change-Id: Ibe1fb67442a854babbc6924fd8437b02cc9e7bcf

util/singleflight/singleflight.go Outdated Show resolved Hide resolved
util/singleflight/singleflight.go Show resolved Hide resolved
}
// Create a context that is not canceled when the parent context is,
// but otherwise propagates all values.
callCtx, callCancel := context.WithCancel(context.WithoutCancel(ctx))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may or may not be the right semantic, but using context.WithoutCancel(ctx) here instead of context.Background() means that the context passed to fn is the context given to first call to DoChanContext. If there are multiple concurrent calls to DoChanContext with different context values, then that could be a surprising semantic.

I don't have a right answer here, but I feel like I would expect the result of fn to be idempotent regardless of what context values is used. Thus, the root of the context given to fn is context.Background and not ctx.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever semantic we choose, this needs to be documented.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed to using context.Background and documented it; we might want to change at some point, but IMO it's easier to require explicit value propagation.

util/singleflight/singleflight.go Show resolved Hide resolved
// finished executing after the last caller has returned.
if c.ctxWaiters.Add(-1) == 0 {
c.cancel()
c.wg.Wait()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have 10 concurrent waiters, I find it odd that 9 return immediately, but then the 10th must wait, but maybe that's the right semantic?

util/singleflight/singleflight_test.go Outdated Show resolved Hide resolved
util/singleflight/singleflight_test.go Outdated Show resolved Hide resolved
util/singleflight/singleflight_test.go Outdated Show resolved Hide resolved
util/singleflight/singleflight_test.go Outdated Show resolved Hide resolved
util/singleflight/singleflight_test.go Outdated Show resolved Hide resolved
This is a variant of DoChan that supports context propagation, such that
the context provided to the inner function will only be canceled when
there are no more waiters for a given key. This can be used to
deduplicate expensive and cancelable calls among multiple callers
safely.

Updates #11935

Signed-off-by: Andrew Dunham <[email protected]>
Change-Id: Ibe1fb67442a854babbc6924fd8437b02cc9e7bcf
@andrew-d andrew-d force-pushed the andrew/singleflight-context branch from ef3fca7 to a93cc9e Compare June 10, 2024 14:00
@andrew-d
Copy link
Member Author

@dsnet because I'm always a bit scared of heavily-concurrent code... mind taking another look at this before I merge? I think I addressed all your comments and the tests still pass with -race, but still 😅

@andrew-d andrew-d requested a review from dsnet June 10, 2024 20:09
@andrew-d andrew-d merged commit 93cd2ab into main Jun 10, 2024
48 checks passed
@andrew-d andrew-d deleted the andrew/singleflight-context branch June 10, 2024 22:38
andrew-d added a commit that referenced this pull request Jun 10, 2024
As an alterative to #11935 using #12003.

Updates #11935

Signed-off-by: Andrew Dunham <[email protected]>
Change-Id: I05f643fe812ceeaec5f266e78e3e529cab3a1ac3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants