fix(cache): make TTL.Load context-aware so callers can cancel while waiting#54
Open
jpugliesi wants to merge 7 commits into
Open
fix(cache): make TTL.Load context-aware so callers can cancel while waiting#54jpugliesi wants to merge 7 commits into
jpugliesi wants to merge 7 commits into
Conversation
…aiting The previous implementation blocked on <-promise.ready with no way to interrupt the wait. When multiple callers share an in-flight singleflight promise, a caller whose context is canceled had to wait for the fetch to complete before receiving an error. Replace the plain channel receive with a select over promise.ready and ctx.Done(). On cancellation the caller returns context.Cause(ctx) immediately; the in-flight goroutine continues to completion and stores the result in cache for future callers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
f367776 to
365a6de
Compare
- Bail out early (under the lock) if the caller's context is already canceled before starting a new fetch, preventing timed-out callers from triggering background provider I/O. - Use a double-select when ctx.Done() wins the race so a completed shared result is preferred over a simultaneous cancellation, avoiding flaky errors for co-waiters near their deadline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TestTTLLoadAlreadyCanceledCacheMiss: verifies that Load with a pre-canceled context on a cache miss returns immediately without invoking fetch or populating the cache. - TestTTLLoadReadyBeatsCancel: stress-tests (1000 iterations, -race) the double-select by unblocking the fetch and canceling the co-waiter simultaneously, ensuring the only outcomes are success or context.Canceled and no other error is returned. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TTL.Loadblocked on<-promise.readywith no way to interrupt the wait, so a caller whose context was canceled had to wait for the shared in-flight fetch to complete before receiving an errorselect { case <-promise.ready: ...; case <-ctx.Done(): ... }context.Cause(ctx)immediately; the in-flight goroutine continues to completion and stores the result for future callers — no goroutine leak, no cache poisoningTTL.Loadcall sites (cache.go,secret/cache.go,secret/authn/cache.go) to passctxas the new first parameterTest plan
go test ./cache/...passes, including newTestTTLLoadContextCancellationwhich verifies a co-waiter with a canceled context returns promptly while the fetch completes and is stored in cache🤖 Generated with Claude Code