github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/privval/retry_signer_client.go (about)

     1  package privval
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/lazyledger/lazyledger-core/crypto"
     8  	tmproto "github.com/lazyledger/lazyledger-core/proto/tendermint/types"
     9  	"github.com/lazyledger/lazyledger-core/types"
    10  )
    11  
    12  // RetrySignerClient wraps SignerClient adding retry for each operation (except
    13  // Ping) w/ a timeout.
    14  type RetrySignerClient struct {
    15  	next    *SignerClient
    16  	retries int
    17  	timeout time.Duration
    18  }
    19  
    20  // NewRetrySignerClient returns RetrySignerClient. If +retries+ is 0, the
    21  // client will be retrying each operation indefinitely.
    22  func NewRetrySignerClient(sc *SignerClient, retries int, timeout time.Duration) *RetrySignerClient {
    23  	return &RetrySignerClient{sc, retries, timeout}
    24  }
    25  
    26  var _ types.PrivValidator = (*RetrySignerClient)(nil)
    27  
    28  func (sc *RetrySignerClient) Close() error {
    29  	return sc.next.Close()
    30  }
    31  
    32  func (sc *RetrySignerClient) IsConnected() bool {
    33  	return sc.next.IsConnected()
    34  }
    35  
    36  func (sc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error {
    37  	return sc.next.WaitForConnection(maxWait)
    38  }
    39  
    40  //--------------------------------------------------------
    41  // Implement PrivValidator
    42  
    43  func (sc *RetrySignerClient) Ping() error {
    44  	return sc.next.Ping()
    45  }
    46  
    47  func (sc *RetrySignerClient) GetPubKey() (crypto.PubKey, error) {
    48  	var (
    49  		pk  crypto.PubKey
    50  		err error
    51  	)
    52  	for i := 0; i < sc.retries || sc.retries == 0; i++ {
    53  		pk, err = sc.next.GetPubKey()
    54  		if err == nil {
    55  			return pk, nil
    56  		}
    57  		// If remote signer errors, we don't retry.
    58  		if _, ok := err.(*RemoteSignerError); ok {
    59  			return nil, err
    60  		}
    61  		time.Sleep(sc.timeout)
    62  	}
    63  	return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err)
    64  }
    65  
    66  func (sc *RetrySignerClient) SignVote(chainID string, vote *tmproto.Vote) error {
    67  	var err error
    68  	for i := 0; i < sc.retries || sc.retries == 0; i++ {
    69  		err = sc.next.SignVote(chainID, vote)
    70  		if err == nil {
    71  			return nil
    72  		}
    73  		// If remote signer errors, we don't retry.
    74  		if _, ok := err.(*RemoteSignerError); ok {
    75  			return err
    76  		}
    77  		time.Sleep(sc.timeout)
    78  	}
    79  	return fmt.Errorf("exhausted all attempts to sign vote: %w", err)
    80  }
    81  
    82  func (sc *RetrySignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error {
    83  	var err error
    84  	for i := 0; i < sc.retries || sc.retries == 0; i++ {
    85  		err = sc.next.SignProposal(chainID, proposal)
    86  		if err == nil {
    87  			return nil
    88  		}
    89  		// If remote signer errors, we don't retry.
    90  		if _, ok := err.(*RemoteSignerError); ok {
    91  			return err
    92  		}
    93  		time.Sleep(sc.timeout)
    94  	}
    95  	return fmt.Errorf("exhausted all attempts to sign proposal: %w", err)
    96  }