Skip to content

Commit 07a72b4

Browse files
committed
fix(services): HealthChecker.Register triggers immediate poll when running
When Register() is called on an already-started HealthChecker, it now sends a non-blocking signal on a new chRefresh channel. The run() goroutine selects on this channel and calls update() immediately, so the newly registered service is visible in IsHealthy() / IsReady() without waiting up to 15 s for the next polling tick. Root cause: the job spawner starts a service then registers it with the HealthChecker. Before this fix, a dynamically registered service was absent from health reports for a full polling interval even though Ready() already returned nil.
1 parent 8115835 commit 07a72b4

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

pkg/services/health.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ func CopyHealth(dest, src map[string]error) {
4747
// HealthChecker is a services.Service which monitors other services and can be probed for system health.
4848
type HealthChecker struct {
4949
StateMachine
50-
chStop chan struct{}
51-
chDone chan struct{}
50+
chStop chan struct{}
51+
chDone chan struct{}
52+
chRefresh chan struct{}
5253

5354
cfg HealthCheckerConfig
5455

@@ -130,12 +131,13 @@ func (cfg HealthCheckerConfig) New() *HealthChecker {
130131
cfg.initVerSha()
131132
cfg.setNoopHooks()
132133
return &HealthChecker{
133-
cfg: cfg,
134-
services: make(map[string]HealthReporter, 10),
135-
healthy: make(map[string]error, 10),
136-
ready: make(map[string]error, 10),
137-
chStop: make(chan struct{}),
138-
chDone: make(chan struct{}),
134+
cfg: cfg,
135+
services: make(map[string]HealthReporter, 10),
136+
healthy: make(map[string]error, 10),
137+
ready: make(map[string]error, 10),
138+
chStop: make(chan struct{}),
139+
chDone: make(chan struct{}),
140+
chRefresh: make(chan struct{}, 1),
139141
}
140142
}
141143

@@ -171,6 +173,8 @@ func (c *HealthChecker) run() {
171173
select {
172174
case <-ticker.C:
173175
c.update(ctx)
176+
case <-c.chRefresh:
177+
c.update(ctx)
174178
case <-c.chStop:
175179
return
176180
}
@@ -226,6 +230,14 @@ func (c *HealthChecker) Register(service HealthReporter) error {
226230
}
227231
}
228232
c.services[name] = service
233+
234+
// Signal the run() goroutine to refresh immediately so the newly
235+
// registered service is visible without waiting for the next tick.
236+
select {
237+
case c.chRefresh <- struct{}{}:
238+
default: // refresh already pending
239+
}
240+
229241
return nil
230242
}
231243

0 commit comments

Comments
 (0)