performHealthCheck pings the active node and triggers failover if unreachable.
()
| 261 | |
| 262 | // performHealthCheck pings the active node and triggers failover if unreachable. |
| 263 | func (cc *ClusterClient) performHealthCheck() { |
| 264 | cc.mu.RLock() |
| 265 | client := cc.activeClient |
| 266 | profile := cc.activeProfile |
| 267 | cc.mu.RUnlock() |
| 268 | |
| 269 | if client == nil { |
| 270 | return |
| 271 | } |
| 272 | |
| 273 | // Use a short timeout for health checks |
| 274 | ctx, cancel := context.WithTimeout(context.Background(), DefaultHealthCheckTimeout) |
| 275 | defer cancel() |
| 276 | |
| 277 | // Ping the version endpoint — lightweight, no auth issues |
| 278 | var result map[string]interface{} |
| 279 | err := client.httpClient.GetWithRetry(ctx, healthCheckPath, &result, 1) |
| 280 | if err != nil { |
| 281 | cc.logger.Error("[CLUSTER] Health check failed for %s: %v", profile, err) |
| 282 | cc.logger.Info("[CLUSTER] Triggering automatic failover") |
| 283 | |
| 284 | // Trigger failover |
| 285 | cc.mu.Lock() |
| 286 | failoverErr := cc.failoverLocked(ctx) |
| 287 | cc.mu.Unlock() |
| 288 | |
| 289 | if failoverErr != nil { |
| 290 | cc.logger.Error("[CLUSTER] Automatic failover failed: %v", failoverErr) |
| 291 | } |
| 292 | return |
| 293 | } |
| 294 | |
| 295 | cc.logger.Debug("[CLUSTER] Health check OK for %s", profile) |
| 296 | } |
| 297 | |
| 298 | // Close stops health checks and cleans up resources. |
| 299 | func (cc *ClusterClient) Close() { |
no test coverage detected