github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/privval/signer_dialer_endpoint.go (about)

     1  package privval
     2  
     3  import (
     4  	"log/slog"
     5  	"time"
     6  
     7  	"github.com/gnolang/gno/tm2/pkg/service"
     8  )
     9  
    10  const (
    11  	defaultMaxDialRetries        = 10
    12  	defaultRetryWaitMilliseconds = 100
    13  )
    14  
    15  // SignerServiceEndpointOption sets an optional parameter on the SignerDialerEndpoint.
    16  type SignerServiceEndpointOption func(*SignerDialerEndpoint)
    17  
    18  // SignerDialerEndpointTimeoutReadWrite sets the read and write timeout for connections
    19  // from external signing processes.
    20  func SignerDialerEndpointTimeoutReadWrite(timeout time.Duration) SignerServiceEndpointOption {
    21  	return func(ss *SignerDialerEndpoint) { ss.timeoutReadWrite = timeout }
    22  }
    23  
    24  // SignerDialerEndpointConnRetries sets the amount of attempted retries to acceptNewConnection.
    25  func SignerDialerEndpointConnRetries(retries int) SignerServiceEndpointOption {
    26  	return func(ss *SignerDialerEndpoint) { ss.maxConnRetries = retries }
    27  }
    28  
    29  // SignerDialerEndpoint dials using its dialer and responds to any
    30  // signature requests using its privVal.
    31  type SignerDialerEndpoint struct {
    32  	signerEndpoint
    33  
    34  	dialer SocketDialer
    35  
    36  	retryWait      time.Duration
    37  	maxConnRetries int
    38  }
    39  
    40  // NewSignerDialerEndpoint returns a SignerDialerEndpoint that will dial using the given
    41  // dialer and respond to any signature requests over the connection
    42  // using the given privVal.
    43  func NewSignerDialerEndpoint(
    44  	logger *slog.Logger,
    45  	dialer SocketDialer,
    46  ) *SignerDialerEndpoint {
    47  	sd := &SignerDialerEndpoint{
    48  		dialer:         dialer,
    49  		retryWait:      defaultRetryWaitMilliseconds * time.Millisecond,
    50  		maxConnRetries: defaultMaxDialRetries,
    51  	}
    52  
    53  	sd.BaseService = *service.NewBaseService(logger, "SignerDialerEndpoint", sd)
    54  	sd.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second
    55  
    56  	return sd
    57  }
    58  
    59  func (sd *SignerDialerEndpoint) ensureConnection() error {
    60  	if sd.IsConnected() {
    61  		return nil
    62  	}
    63  
    64  	retries := 0
    65  	for retries < sd.maxConnRetries {
    66  		conn, err := sd.dialer()
    67  
    68  		if err != nil {
    69  			retries++
    70  			sd.Logger.Debug("SignerDialer: Reconnection failed", "retries", retries, "max", sd.maxConnRetries, "err", err)
    71  			// Wait between retries
    72  			time.Sleep(sd.retryWait)
    73  		} else {
    74  			sd.SetConnection(conn)
    75  			sd.Logger.Debug("SignerDialer: Connection Ready")
    76  			return nil
    77  		}
    78  	}
    79  
    80  	sd.Logger.Debug("SignerDialer: Max retries exceeded", "retries", retries, "max", sd.maxConnRetries)
    81  
    82  	return ErrNoConnection
    83  }