@@ -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
343343func (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
372420func (mc * Client ) isConnectionError (err error ) bool {
373421 if err == nil {
0 commit comments