Skip to content

Commit fc023b8

Browse files
auricomclaude
andcommitted
fix(raft): preserve stdlib logger writer in bolt filter; propagate ctx through ResignLeader
- suppressBoltNoise.Do now wraps log.Writer() instead of os.Stderr so any existing stdlib logger redirection is preserved rather than clobbered - ResignLeader now accepts a context.Context: leadershipTransfer runs in a goroutine and a select abandons the caller at ctx.Done(), returning ctx.Err(); the goroutine itself exits once the inner raft transfer completes (bounded by ElectionTimeout) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4d105a2 commit fc023b8

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

pkg/raft/node.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func buildRaftConfig(cfg *Config) *raft.Config {
9393

9494
func NewNode(cfg *Config, logger zerolog.Logger) (*Node, error) {
9595
suppressBoltNoise.Do(func() {
96-
log.SetOutput(&boltTxClosedFilter{w: os.Stderr})
96+
log.SetOutput(&boltTxClosedFilter{w: log.Writer()})
9797
})
9898
if err := os.MkdirAll(cfg.RaftDir, 0755); err != nil {
9999
return nil, fmt.Errorf("create raft dir: %w", err)
@@ -278,11 +278,19 @@ func (n *Node) leadershipTransfer() error {
278278
// It is a no-op when the node is nil or not currently the leader.
279279
// Call this before cancelling the node context on graceful shutdown to minimise
280280
// the window where a dying leader could still serve blocks.
281-
func (n *Node) ResignLeader() error {
281+
// The transfer is abandoned and ctx.Err() is returned if ctx expires first.
282+
func (n *Node) ResignLeader(ctx context.Context) error {
282283
if n == nil || !n.IsLeader() {
283284
return nil
284285
}
285-
return n.leadershipTransfer()
286+
done := make(chan error, 1)
287+
go func() { done <- n.leadershipTransfer() }()
288+
select {
289+
case err := <-done:
290+
return err
291+
case <-ctx.Done():
292+
return ctx.Err()
293+
}
286294
}
287295

288296
func (n *Node) Config() Config {

pkg/raft/node_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,13 @@ func TestNodeStartNilNoop(t *testing.T) {
183183

184184
func TestNodeResignLeader_NilNoop(t *testing.T) {
185185
var n *Node
186-
assert.NoError(t, n.ResignLeader())
186+
assert.NoError(t, n.ResignLeader(context.Background()))
187187
}
188188

189189
func TestNodeResignLeader_NotLeaderNoop(t *testing.T) {
190190
// Non-nil node with nil raft field — IsLeader() returns false, no transfer attempted.
191191
n := &Node{}
192-
assert.NoError(t, n.ResignLeader())
192+
assert.NoError(t, n.ResignLeader(context.Background()))
193193
}
194194

195195
func TestNewNode_SnapshotConfigApplied(t *testing.T) {

0 commit comments

Comments
 (0)