Skip to content

fix(raft): electionLoop 复用 timer, 按 Stop→drain→Reset 顺序更新#40

Merged
NeverENG merged 1 commit into
mainfrom
fix/raft-timer
May 21, 2026
Merged

fix(raft): electionLoop 复用 timer, 按 Stop→drain→Reset 顺序更新#40
NeverENG merged 1 commit into
mainfrom
fix/raft-timer

Conversation

@NeverENG
Copy link
Copy Markdown
Owner

@NeverENG NeverENG commented May 21, 2026

Summary

  • `NewRaftWithDataDir` 内 `time.NewTimer` 一次性初始化 `r.timer`
  • `electionLoop` 不再每轮 `time.NewTimer`, 只 select; reset 由独立 `resetElectionTimer` 处理
  • `resetElectionTimer` 用标准三步: `Stop()` → 必要时 drain `timer.C` → 重新随机 `electionTimeout` → `Reset`

Background

原代码 `for { r.timer = time.NewTimer(timeout); select{...} }` 每轮新建 timer, GC 压力 + 偶发的旧 timer fire 写入新 timer 的 channel 风险。改为复用单一 timer + 标准 Stop/drain/Reset 序列, 符合 Go 官方 timer.Reset 文档建议。

Test plan

  • `go build ./Raft/...` 通过
  • `go vet ./Raft/...` 通过
  • raft_test.go 14 用例全部通过 (清掉残留 raft_data/raft_test_data_* 后), 含 `TestElectionTimeout`

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Optimized election timer handling in the Raft consensus mechanism for improved efficiency and reliability. Single reusable timer now replaces repeated timer creation, reducing resource usage and enhancing election timing accuracy.

Review Change Stack

之前每次循环 time.NewTimer, 既浪费 GC, 又使 heartbeatCh/electionCh 触发时新随机的 timeout 跟旧的 timeout 不一致, 偏离 Raft 规范 (election 超时应在每轮 election 结束后重新选取, 而不是每次心跳)。

- NewRaftWithDataDir 内 time.NewTimer 一次, 用 r.electionTimeout
- electionLoop 仅 select; 抽出 resetElectionTimer 用标准 Stop→drain→Reset 三步
- timeout 在每次 reset 时重新随机, 既保留原行为又避免 timer leak

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 28d4ef37-5e56-445b-b8e7-efbe1d35ad0f

📥 Commits

Reviewing files that changed from the base of the PR and between bfff8bc and 0b0c854.

📒 Files selected for processing (1)
  • Raft/raft.go

📝 Walkthrough

Walkthrough

Election timer management is refactored from allocating a fresh timer on each loop iteration to reusing a single timer object. The constructor initializes the timer, and the election loop uses, resets, and re-arms it across multiple cycles while properly draining stale signals.

Changes

Election Timer Reuse

Layer / File(s) Summary
Timer initialization in constructor
Raft/raft.go
Constructor creates a reusable election time.Timer with the initial randomized election timeout immediately after commitCond setup.
Election loop with reusable timer
Raft/raft.go
electionLoop selects on the shared timer channel and calls resetElectionTimer after election start or receiving heartbeat/election signals. resetElectionTimer performs Stop→drain→randomize→Reset to maintain consistent election timing and avoid spurious wakeups.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A timer born, then reused with care,
No more wasteful cycles in the air,
Stop, drain, reset—a rhythm so fair,
Elections tick in the Raft's affair! 🎪

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/raft-timer

Comment @coderabbitai help to get the list of available commands and usage tips.

@NeverENG NeverENG merged commit 6209aa8 into main May 21, 2026
2 of 3 checks passed
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