From 27fb45b388a204bd2569734fb228d2938a368a7c Mon Sep 17 00:00:00 2001 From: Brandur Date: Sun, 12 Apr 2026 12:49:13 -0500 Subject: [PATCH] Make `leaderResignedChan` buffered to protect against hang This one's aimed at fixing an intermittently failing tests that we're occasionally seeing in CI: https://github.com/riverqueue/river/actions/runs/24312334093/job/70984031771?pr=1203 It was possible for the test case to end to `leaderResignedChan` before `keepLeadershipLoop` entered its select, which with an unbuffered channel, could block forever. Changing this to a buffered channel lets `keepLeadershipLoop` consume the value as its leisure while making sure the send never blocks. --- internal/leadership/elector.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/leadership/elector.go b/internal/leadership/elector.go index 69ddd75c..7cac3243 100644 --- a/internal/leadership/elector.go +++ b/internal/leadership/elector.go @@ -136,8 +136,10 @@ func (e *Elector) Start(ctx context.Context) error { return nil } - // We'll send to this channel anytime a leader resigns on the key with `name` - e.leaderResignedChan = make(chan struct{}) + // We'll send to this channel anytime a leader resigns on the key with `name`. + // Buffered to 1 so a send doesn't block if the receiving loop hasn't entered + // its select yet (e.g. between gaining and maintaining leadership). + e.leaderResignedChan = make(chan struct{}, 1) e.requestResignChan = make(chan struct{})