Skip to content

Commit 4baa5fa

Browse files
author
Marvin Zhang
committed
fix(grpc/client): trigger reconnection on bad conn state and improve connection logging
- Trigger reconnection proactively from Get*WithTimeout when underlying connection is in SHUTDOWN or TRANSIENT_FAILURE to avoid returning stale/unusable clients. - Add debug/info logs around client registration, connection attempts, closing existing connections, connection initiation, reconnection start, backoff retry and successful reconnection (including current state and registration status). - Surface more context in reconnection and connection logs to aid diagnostics.
1 parent 6020fef commit 4baa5fa

1 file changed

Lines changed: 35 additions & 3 deletions

File tree

core/grpc/client/client.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ func (c *GrpcClient) WaitForReady() {
212212
}
213213

214214
func (c *GrpcClient) register() {
215+
c.Debugf("registering gRPC service clients")
215216
c.nodeClient = grpc2.NewNodeServiceClient(c.conn)
216217
c.modelBaseServiceClient = grpc2.NewModelBaseServiceClient(c.conn)
217218
c.taskClient = grpc2.NewTaskServiceClient(c.conn)
@@ -224,6 +225,7 @@ func (c *GrpcClient) register() {
224225

225226
// Mark as registered
226227
c.setRegistered(true)
228+
c.Infof("gRPC service clients successfully registered")
227229
}
228230

229231
func (c *GrpcClient) Context() (ctx context.Context, cancel context.CancelFunc) {
@@ -503,6 +505,11 @@ func (c *GrpcClient) GetNodeClientWithTimeout(timeout time.Duration) (grpc2.Node
503505
if c.stopped {
504506
return nil, fmt.Errorf("grpc client is stopped")
505507
}
508+
// Check if connection is in bad state and needs reconnection
509+
if c.conn != nil && (c.conn.GetState() == connectivity.Shutdown || c.conn.GetState() == connectivity.TransientFailure) {
510+
c.Debugf("connection in bad state (%s), triggering reconnection", c.conn.GetState())
511+
c.triggerReconnection(fmt.Sprintf("bad connection state: %s", c.conn.GetState()))
512+
}
506513
if !c.IsRegistered() {
507514
if err := c.waitForRegisteredWithTimeout(timeout); err != nil {
508515
return nil, fmt.Errorf("failed to get node client: %w", err)
@@ -515,6 +522,11 @@ func (c *GrpcClient) GetTaskClientWithTimeout(timeout time.Duration) (grpc2.Task
515522
if c.stopped {
516523
return nil, fmt.Errorf("grpc client is stopped")
517524
}
525+
// Check if connection is in bad state and needs reconnection
526+
if c.conn != nil && (c.conn.GetState() == connectivity.Shutdown || c.conn.GetState() == connectivity.TransientFailure) {
527+
c.Debugf("connection in bad state (%s), triggering reconnection", c.conn.GetState())
528+
c.triggerReconnection(fmt.Sprintf("bad connection state: %s", c.conn.GetState()))
529+
}
518530
if !c.IsRegistered() {
519531
if err := c.waitForRegisteredWithTimeout(timeout); err != nil {
520532
return nil, fmt.Errorf("failed to get task client: %w", err)
@@ -527,6 +539,11 @@ func (c *GrpcClient) GetModelBaseServiceClientWithTimeout(timeout time.Duration)
527539
if c.stopped {
528540
return nil, fmt.Errorf("grpc client is stopped")
529541
}
542+
// Check if connection is in bad state and needs reconnection
543+
if c.conn != nil && (c.conn.GetState() == connectivity.Shutdown || c.conn.GetState() == connectivity.TransientFailure) {
544+
c.Debugf("connection in bad state (%s), triggering reconnection", c.conn.GetState())
545+
c.triggerReconnection(fmt.Sprintf("bad connection state: %s", c.conn.GetState()))
546+
}
530547
if !c.IsRegistered() {
531548
if err := c.waitForRegisteredWithTimeout(timeout); err != nil {
532549
return nil, fmt.Errorf("failed to get model base service client: %w", err)
@@ -539,6 +556,11 @@ func (c *GrpcClient) GetDependencyClientWithTimeout(timeout time.Duration) (grpc
539556
if c.stopped {
540557
return nil, fmt.Errorf("grpc client is stopped")
541558
}
559+
// Check if connection is in bad state and needs reconnection
560+
if c.conn != nil && (c.conn.GetState() == connectivity.Shutdown || c.conn.GetState() == connectivity.TransientFailure) {
561+
c.Debugf("connection in bad state (%s), triggering reconnection", c.conn.GetState())
562+
c.triggerReconnection(fmt.Sprintf("bad connection state: %s", c.conn.GetState()))
563+
}
542564
if !c.IsRegistered() {
543565
if err := c.waitForRegisteredWithTimeout(timeout); err != nil {
544566
return nil, fmt.Errorf("failed to get dependency client: %w", err)
@@ -551,6 +573,11 @@ func (c *GrpcClient) GetMetricClientWithTimeout(timeout time.Duration) (grpc2.Me
551573
if c.stopped {
552574
return nil, fmt.Errorf("grpc client is stopped")
553575
}
576+
// Check if connection is in bad state and needs reconnection
577+
if c.conn != nil && (c.conn.GetState() == connectivity.Shutdown || c.conn.GetState() == connectivity.TransientFailure) {
578+
c.Debugf("connection in bad state (%s), triggering reconnection", c.conn.GetState())
579+
c.triggerReconnection(fmt.Sprintf("bad connection state: %s", c.conn.GetState()))
580+
}
554581
if !c.IsRegistered() {
555582
if err := c.waitForRegisteredWithTimeout(timeout); err != nil {
556583
return nil, fmt.Errorf("failed to get metric client: %w", err)
@@ -706,18 +733,19 @@ func (c *GrpcClient) executeReconnection() {
706733
c.reconnectMux.Unlock()
707734
}()
708735

709-
c.Infof("executing reconnection to %s", c.address)
736+
c.Infof("executing reconnection to %s (current state: %s)", c.address, c.getState())
710737

711738
if err := c.doConnect(); err != nil {
712739
c.Errorf("reconnection failed: %v", err)
713740
c.recordFailure()
714741

715742
// Exponential backoff before allowing next attempt
716743
backoffDuration := c.calculateBackoff()
744+
c.Warnf("will retry reconnection after %v backoff", backoffDuration)
717745
time.Sleep(backoffDuration)
718746
} else {
719747
c.recordSuccess()
720-
c.Infof("reconnection successful")
748+
c.Infof("reconnection successful - connection state: %s, registered: %v", c.getState(), c.IsRegistered())
721749
}
722750
}
723751

@@ -795,10 +823,12 @@ func (c *GrpcClient) calculateBackoff() time.Duration {
795823
}
796824

797825
func (c *GrpcClient) doConnect() error {
826+
c.Debugf("attempting connection to %s", c.address)
798827
c.setRegistered(false)
799828

800829
// Close existing connection
801830
if c.conn != nil {
831+
c.Debugf("closing existing connection (state: %s)", c.conn.GetState())
802832
c.conn.Close()
803833
c.conn = nil
804834
}
@@ -817,14 +847,16 @@ func (c *GrpcClient) doConnect() error {
817847
ctx, cancel := context.WithTimeout(context.Background(), connectionTimeout)
818848
defer cancel()
819849

850+
c.Debugf("initiating connection to %s", c.address)
820851
c.conn.Connect()
821852
if err := c.waitForConnectionReady(ctx); err != nil {
853+
c.Errorf("failed to reach ready state: %v", err)
822854
c.conn.Close()
823855
c.conn = nil
824856
return err
825857
}
826858

827-
c.Infof("connected to %s", c.address)
859+
c.Infof("connected to %s (state: %s)", c.address, c.conn.GetState())
828860
c.register()
829861

830862
return nil

0 commit comments

Comments
 (0)