Skip to content

Commit 07bb035

Browse files
committed
Enhance client health check and reconnection logic
- Updated performHealthCheck to include automatic reconnection attempts on error state with exponential backoff. - Introduced tryReconnect method for handling reconnection attempts with proper error logging and state management. - Improved overall connection handling and logging for better traceability during reconnection processes.
1 parent 698dc5c commit 07bb035

1 file changed

Lines changed: 49 additions & 1 deletion

File tree

internal/upstream/managed/client.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,19 @@ func (mc *Client) backgroundHealthCheck() {
339339
}
340340
}
341341

342-
// performHealthCheck checks if the connection is still healthy
342+
// performHealthCheck checks if the connection is still healthy and attempts reconnection if needed
343343
func (mc *Client) performHealthCheck() {
344+
// Check if client is in error state and should retry connection
345+
if mc.StateManager.GetState() == types.StateError && mc.ShouldRetry() {
346+
mc.logger.Info("Attempting automatic reconnection with exponential backoff",
347+
zap.String("server", mc.Config.Name),
348+
zap.Int("retry_count", mc.StateManager.GetConnectionInfo().RetryCount))
349+
350+
mc.tryReconnect()
351+
return
352+
}
353+
354+
// Skip health checks if not connected or for Docker containers
344355
if !mc.IsConnected() {
345356
return
346357
}
@@ -368,6 +379,43 @@ func (mc *Client) performHealthCheck() {
368379
}
369380
}
370381

382+
// tryReconnect attempts to reconnect the client with proper error handling
383+
func (mc *Client) tryReconnect() {
384+
// Create a timeout context for the reconnection attempt
385+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
386+
defer cancel()
387+
388+
mc.logger.Info("Starting reconnection attempt",
389+
zap.String("server", mc.Config.Name),
390+
zap.String("current_state", mc.StateManager.GetState().String()))
391+
392+
// First, disconnect the current client to clean up any broken connections
393+
// We don't need to hold the mutex here as Disconnect() already handles it
394+
if err := mc.coreClient.Disconnect(); err != nil {
395+
mc.logger.Warn("Failed to disconnect during reconnection attempt",
396+
zap.String("server", mc.Config.Name),
397+
zap.Error(err))
398+
}
399+
400+
// Reset state to disconnected before attempting reconnection
401+
mc.StateManager.Reset()
402+
403+
// Attempt to reconnect using the existing Connect method
404+
// The Connect method already handles state transitions and error management
405+
if err := mc.Connect(ctx); err != nil {
406+
mc.logger.Error("Reconnection attempt failed",
407+
zap.String("server", mc.Config.Name),
408+
zap.Error(err),
409+
zap.Int("retry_count", mc.StateManager.GetConnectionInfo().RetryCount))
410+
// Connect method already sets the error state, so we don't need to do it here
411+
return
412+
}
413+
414+
mc.logger.Info("Reconnection attempt successful",
415+
zap.String("server", mc.Config.Name),
416+
zap.String("new_state", mc.StateManager.GetState().String()))
417+
}
418+
371419
// isConnectionError checks if an error indicates a connection problem
372420
func (mc *Client) isConnectionError(err error) bool {
373421
if err == nil {

0 commit comments

Comments
 (0)