Skip to content

fix: speed up hakeeper bootstrap - #26760

Open
volgariver6 wants to merge 3 commits into
matrixorigin:mainfrom
volgariver6:fix/hakeeper-startup-speed
Open

fix: speed up hakeeper bootstrap#26760
volgariver6 wants to merge 3 commits into
matrixorigin:mainfrom
volgariver6:fix/hakeeper-startup-speed

Conversation

@volgariver6

@volgariver6 volgariver6 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #26699

What this PR does / why we need it:

This reduces HAKeeper bootstrap latency by making bootstrap-phase checks and heartbeats more responsive while preserving the configured steady-state check interval. The previous path waited on coarse polling intervals while HAKeeper elected a leader, accepted initial cluster info, generated bootstrap commands, and reported running state. That made tests such as TestSpeedupAbortAllTxn spend unnecessary time before the SQL workload started.

Changes

  • Wait for the HAKeeper leader before setting initial cluster info.
  • Trigger an immediate heartbeat after initial cluster info/bootstrap commands are accepted.
  • Use a shorter HAKeeper check interval only while bootstrap is not running yet, then return to the configured steady-state interval.
  • Reduce embed cluster wait polling from one second to 100ms and throttle retry logs.
  • Make test cluster setup set initial cluster info through the elected HAKeeper leader.

Tests

  • GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^TestSpeedupAbortAllTxn$' -count=1 -timeout=180s ./pkg/tests/issues
  • GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestClusterConditionCheckInterval|Test_waitHAKeeperRunningLocked|Test_waitAnyShardReadyLocked|TestHAKeeperRunningTimeout|TestWaitClusterConditionClosesHAKeeperClient)$' -count=1 -timeout=120s ./pkg/embed
  • GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^TestSetInitialClusterInfoUsesHAKeeperLeader$' -count=1 -timeout=60s ./pkg/tests/service
  • GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestServiceBootstrapRestoresHAKeeperAndWAL|TestSetInitialClusterInfo|TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval|TestBootstrap|TestFailedBootstrap)$' -count=1 -timeout=180s ./pkg/logservice
  • git diff --check HEAD

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to speed up HAKeeper bootstrap (especially in test environments) by making HAKeeper state checks more responsive during bootstrap phases and by triggering earlier heartbeats when bootstrap progress is made.

Changes:

  • Make HAKeeper check interval adaptive (faster during bootstrap, normal when running) and wire it into the store ticker loop.
  • Trigger logservice heartbeats on key bootstrap events to accelerate state propagation.
  • Add/adjust unit tests for the new bootstrap/check-interval behaviors and leader selection in test clusters.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pkg/tests/service/service.go Passes context into initial cluster-info initialization during logservice startup.
pkg/tests/service/logservice.go Updates cluster-info initialization to target the HAKeeper leader.
pkg/tests/service/service_test.go Adds a unit test ensuring initial cluster info is set via the HAKeeper leader.
pkg/logservice/store.go Replaces fixed HAKeeper check ticker with an adaptive timer; adds bootstrap callbacks/state for responsiveness.
pkg/logservice/store_hakeeper_check.go Introduces adaptive check interval logic and returns state from hakeeperCheck for scheduling decisions.
pkg/logservice/store_hakeeper_check_test.go Adds tests for adaptive interval logic and bootstrap callback invocation.
pkg/logservice/service.go Adds heartbeat trigger channel wiring via bootstrap callback.
pkg/logservice/service_commands.go Adds an explicit on-demand heartbeat trigger path.
pkg/logservice/service_bootstrap.go Waits for leader readiness before proposing initial cluster info; requests heartbeat after proposal.
pkg/embed/operator.go Speeds up polling loops (smaller sleep) and throttles logs while waiting for cluster conditions.
pkg/embed/operator_test.go Adds a unit test for the new polling interval.

Comment on lines +257 to +265
func (l *store) nextHAKeeperCheckInterval(state *pb.CheckerState) time.Duration {
interval := l.cfg.HAKeeperCheckInterval.Duration
if state == nil || state.State != pb.HAKeeperRunning {
if interval > bootstrapHAKeeperCheckInterval {
return bootstrapHAKeeperCheckInterval
}
}
return interval
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 33cdfa7. nil checker state now keeps the configured HAKeeper check interval, so non-leader LogServices do not stay on the 100ms bootstrap cadence. Verified with GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestServiceBootstrapRestoresHAKeeperAndWAL|TestSetInitialClusterInfo|TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval|TestBootstrap|TestFailedBootstrap)$' -count=1 -timeout=180s ./pkg/logservice.

Comment on lines +50 to +67
func TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval(t *testing.T) {
s := &store{
cfg: Config{
HAKeeperCheckInterval: toml.Duration{Duration: 3 * time.Second},
},
}

require.Equal(t, bootstrapHAKeeperCheckInterval, s.nextHAKeeperCheckInterval(nil))
require.Equal(t, bootstrapHAKeeperCheckInterval, s.nextHAKeeperCheckInterval(&pb.CheckerState{
State: pb.HAKeeperBootstrapping,
}))
require.Equal(t, bootstrapHAKeeperCheckInterval, s.nextHAKeeperCheckInterval(&pb.CheckerState{
State: pb.HAKeeperBootstrapCommandsReceived,
}))
require.Equal(t, 3*time.Second, s.nextHAKeeperCheckInterval(&pb.CheckerState{
State: pb.HAKeeperRunning,
}))
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 33cdfa7. The test now asserts nil uses the configured interval, adds an explicit HAKeeperCreated bootstrap case, and checks the separate initial fast interval helper. Verified with GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestServiceBootstrapRestoresHAKeeperAndWAL|TestSetInitialClusterInfo|TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval|TestBootstrap|TestFailedBootstrap)$' -count=1 -timeout=180s ./pkg/logservice.

Comment on lines 274 to +276
case pb.HAKeeperCreated:
l.runtime.Logger().Warn("waiting for initial cluster info to be set, check skipped")
return
return state

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 33cdfa7. The HAKeeperCreated warning is now throttled to once per second using the existing bootstrap log timestamp. Verified with GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestServiceBootstrapRestoresHAKeeperAndWAL|TestSetInitialClusterInfo|TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval|TestBootstrap|TestFailedBootstrap)$' -count=1 -timeout=180s ./pkg/logservice.

Comment thread pkg/logservice/service.go
Comment on lines 74 to 78
stopper *stopper.Stopper
haClient LogHAKeeperClient
fileService fileservice.FileService
heartbeatC chan struct{}
shutdownC chan struct{}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Updated the PR title to fix: speed up hakeeper bootstrap and adjusted the body to describe the runtime bootstrap responsiveness and steady-state interval behavior.

Comment thread pkg/logservice/store.go Outdated
Comment on lines +1235 to +1236
haTimer := time.NewTimer(l.nextHAKeeperCheckInterval(nil))
defer haTimer.Stop()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 33cdfa7. The ticker now starts with a separate initial fast interval, while subsequent nil states use the configured interval. Verified with GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestServiceBootstrapRestoresHAKeeperAndWAL|TestSetInitialClusterInfo|TestNextHAKeeperCheckIntervalUsesFastBootstrapInterval|TestBootstrap|TestFailedBootstrap)$' -count=1 -timeout=180s ./pkg/logservice.

Comment on lines +244 to 246
leader := c.WaitHAKeeperLeader(ctx)
err = leader.SetInitialClusterInfo(
c.opt.initial.logShardNum,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 33cdfa7. setInitialClusterInfo now caches the once.Do result on the test cluster instead of waiting on a per-call channel, and TestSetInitialClusterInfoCanBeCalledAgain covers the second-call path. Verified with GOPROXY=https://goproxy.cn,direct .agents/skills/mo-dev/scripts/mo-cgo-test -v -run '^(TestSetInitialClusterInfoUsesHAKeeperLeader|TestSetInitialClusterInfoCanBeCalledAgain)$' -count=1 -timeout=60s ./pkg/tests/service.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

pkg/tests/service/logservice.go:243

  • setInitialClusterInfo now calls WaitHAKeeperLeader(), which polls every 100ms. WaitHAKeeperLeader/getHAKeeperLeader currently emit an Info log ("hakeeper state") on every poll for each started HAKeeper service (see pkg/tests/service/service.go:1613-1617). During slow leader election this can spam CI logs and slow tests. Consider throttling that log (e.g., once per second) or reducing it to Debug during leader-wait loops.
		c.logger.Info("initialize cluster information")

		leader := c.WaitHAKeeperLeader(ctx)
		err = leader.SetInitialClusterInfo(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bug Something isn't working size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants