Skip to content

Buffered requestResignChan#1207

Open
brandur wants to merge 1 commit intomasterfrom
brandur-buffered-request-resign-chan
Open

Buffered requestResignChan#1207
brandur wants to merge 1 commit intomasterfrom
brandur-buffered-request-resign-chan

Conversation

@brandur
Copy link
Copy Markdown
Contributor

@brandur brandur commented Apr 12, 2026

Aims to fix another intermittent test failure:

https://github.com/riverqueue/river/actions/runs/24312716933/job/70985012980?pr=1205

--- FAIL: TestElector_WithNotifier (0.00s)
    --- FAIL: TestElector_WithNotifier/RequestResignStress (20.41s)
        elector_test.go:350: Generated postgres schema "leadership_2026_04_12t17_52_43_schema_04" with migrations [1 2 3 4 5 6] on line "main" in 229.626141ms [4 generated] [0 reused]
        elector_test.go:352: Starting test_client_id
        elector_test.go:375: Requesting leadership resign
        elector_test.go:375: Requesting leadership resign
        elector_test.go:375: Requesting leadership resign
        elector_test.go:375: Requesting leadership resign
        elector_test.go:375: Requesting leadership resign
        test_signal.go:95: timed out waiting on test signal after 10s
        test_signal.go:95: timed out waiting on test signal after 10s
        riverdbtest.go:293: Checked in postgres schema "leadership_2026_04_12t17_52_43_schema_04"; 1 idle schema(s) [5 generated] [3 reused]
FAIL
FAIL	github.com/riverqueue/river/internal/leadership	20.948s

The problem is that when requestResignChan is unbuffered, if
keepLeadershipLoop hasn't yet entered its select, then the default
statement on the select below will cause all senders (we have 5
competing senders in the RequestResignStress test case) to fall
through without sending anything:

select {
case <-ctx.Done():
case e.requestResignChan <- struct{}{}:
default:
        // if context is not done and requestResignChan has an item in it
        // already, do nothing
}

By making the channel buffered, we guarantee at least one sender gets a
message through, and we don't end up hanging the test.

Aims to fix another intermittent test failure:

https://github.com/riverqueue/river/actions/runs/24312716933/job/70985012980?pr=1205

    --- FAIL: TestElector_WithNotifier (0.00s)
        --- FAIL: TestElector_WithNotifier/RequestResignStress (20.41s)
            elector_test.go:350: Generated postgres schema "leadership_2026_04_12t17_52_43_schema_04" with migrations [1 2 3 4 5 6] on line "main" in 229.626141ms [4 generated] [0 reused]
            elector_test.go:352: Starting test_client_id
            elector_test.go:375: Requesting leadership resign
            elector_test.go:375: Requesting leadership resign
            elector_test.go:375: Requesting leadership resign
            elector_test.go:375: Requesting leadership resign
            elector_test.go:375: Requesting leadership resign
            test_signal.go:95: timed out waiting on test signal after 10s
            test_signal.go:95: timed out waiting on test signal after 10s
            riverdbtest.go:293: Checked in postgres schema "leadership_2026_04_12t17_52_43_schema_04"; 1 idle schema(s) [5 generated] [3 reused]
    FAIL
    FAIL	github.com/riverqueue/river/internal/leadership	20.948s

The problem is that when `requestResignChan` is unbuffered, if
`keepLeadershipLoop` hasn't yet entered its `select`, then the `default`
statement on the `select` below will cause all senders (we have 5
competing senders in the `RequestResignStress` test case) to fall
through without sending anything:

    select {
    case <-ctx.Done():
    case e.requestResignChan <- struct{}{}:
    default:
            // if context is not done and requestResignChan has an item in it
            // already, do nothing
    }

By making the channel buffered, we guarantee at least one sender gets a
message through, and we don't end up hanging the test.
@brandur
Copy link
Copy Markdown
Contributor Author

brandur commented Apr 12, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@brandur brandur requested a review from bgentry April 12, 2026 18:19
@brandur
Copy link
Copy Markdown
Contributor Author

brandur commented Apr 12, 2026

@bgentry Again, kind of hoping that we can rely on Claude/Codex to cross reference their work and root out any tricky concurrency problems here.

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.

1 participant