Skip to content

chore: add singleflightcheck analyzer to enforce context-aware singleflight#2954

Merged
tstirrat15 merged 1 commit intoauthzed:mainfrom
josephschorr:singleflight-ctx
Mar 10, 2026
Merged

chore: add singleflightcheck analyzer to enforce context-aware singleflight#2954
tstirrat15 merged 1 commit intoauthzed:mainfrom
josephschorr:singleflight-ctx

Conversation

@josephschorr
Copy link
Member

Adds a custom analyzer that detects uses of golang.org/x/sync/singleflight in functions with a context.Context parameter, requiring resenje.org/singleflight instead. The resenje variant is context-aware and supports generics, preventing context cancellation from being silently ignored in singleflighted calls.

Migrate the two remaining callsites (optimized revisions and schema caching) to resenje.org/singleflight.

Fixes #2953

@josephschorr josephschorr requested a review from a team as a code owner March 5, 2026 22:20
@github-actions github-actions bot added area/datastore Affects the storage system area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools) labels Mar 5, 2026
@josephschorr josephschorr force-pushed the singleflight-ctx branch 2 times, most recently from 2d46179 to 44b9aa8 Compare March 5, 2026 22:54
Copy link
Contributor

@tstirrat15 tstirrat15 left a comment

Choose a reason for hiding this comment

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

See comment

// We couldn't use the cached entry, load one
var err error
loadedRaw, err, _ := r.p.readGroup.Do(cacheRevisionKey, func() (any, error) {
loadedEntry, _, err := r.p.readGroup.Do(ctx, cacheRevisionKey, func(ctx context.Context) (*cacheEntry, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

For this and the other callsite: we're now passing the context which means it can be cancelled, but do we know that both of these codepaths have timeouts on them somewhere further up the chain?

Copy link
Contributor

Choose a reason for hiding this comment

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

i'm wondering why we didn't act defensively and added a context timeout anyway..

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'm wondering why we didn't act defensively and added a context timeout anyway..

That was my proposal: we wrap this (and any other singleflight) calls in a timeout anyway, but since we didn't get consensus, I did this portion first

Copy link
Member Author

Choose a reason for hiding this comment

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

but do we know that both of these codepaths have timeouts on them somewhere further up the chain?

Yes, all requests have timeouts ultimately from the API layer that moves downward into here (except for writes, which break the context, but have their own timeouts)

@codecov
Copy link

codecov bot commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.83%. Comparing base (cf317c7) to head (d27c4fe).

❌ Your project check has failed because the head coverage (74.83%) is below the target coverage (75.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2954      +/-   ##
==========================================
+ Coverage   74.77%   74.83%   +0.06%     
==========================================
  Files         494      494              
  Lines       60623    60622       -1     
==========================================
+ Hits        45323    45358      +35     
+ Misses      12136    12115      -21     
+ Partials     3164     3149      -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

"-protomarshalcheck",
"-telemetryconvcheck",
"-iferrafterrowclosecheck",
"-singleflightcheck",
Copy link
Contributor

Choose a reason for hiding this comment

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

use depguard please

settings:
    depguard:
      rules:
        main:
          deny:
            - pkg: "golang.org/x/sync/singleflight"
              desc: "use resenje.org/singleflight instead so that we can break out of deadlocks"

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the idea was that there may be places where you want to singleflight and don't have access to a context object. Unless we're saying that we'd want to create a context with timeout at that callsite?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can't use depguard: there are times when we need to use singleflight without context being available; the linter only checks the cases where context is available

…flight

Add a custom analyzer that detects uses of golang.org/x/sync/singleflight
in functions with a context.Context parameter, requiring resenje.org/singleflight
instead. The resenje variant is context-aware and supports generics, preventing
context cancellation from being silently ignored in singleflighted calls.

Migrate the two remaining callsites (optimized revisions and schema caching)
to resenje.org/singleflight.

Fixes authzed#2953
Copy link
Contributor

@tstirrat15 tstirrat15 left a comment

Choose a reason for hiding this comment

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

LGTM

@tstirrat15 tstirrat15 enabled auto-merge (squash) March 10, 2026 19:27
@tstirrat15 tstirrat15 merged commit 0e16dd1 into authzed:main Mar 10, 2026
43 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Mar 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area/datastore Affects the storage system area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools) Skip-Changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use context-aware singleflight package across the repo

3 participants