github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/retry.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"time"
     8  
     9  	json "github.com/minio/colorjson"
    10  	"github.com/minio/mc/pkg/probe"
    11  )
    12  
    13  type retryManager struct {
    14  	retries       int
    15  	maxRetries    int
    16  	retryInterval time.Duration
    17  	commandCtx    context.Context
    18  	retryCtx      context.Context
    19  	cancelRetry   context.CancelFunc
    20  }
    21  
    22  func newRetryManager(ctx context.Context, retryInterval time.Duration, maxRetries int) *retryManager {
    23  	retryCtx, cancelFunc := context.WithCancel(context.Background())
    24  	return &retryManager{
    25  		retryInterval: retryInterval,
    26  		maxRetries:    maxRetries,
    27  		commandCtx:    ctx,
    28  		retryCtx:      retryCtx,
    29  		cancelRetry:   cancelFunc,
    30  	}
    31  }
    32  
    33  type retryMessage struct {
    34  	SourceURL string `json:"sourceURL"`
    35  	TargetURL string `json:"targetURL"`
    36  	Retries   int    `json:"retries"`
    37  }
    38  
    39  func (r retryMessage) String() string {
    40  	return fmt.Sprintf("<INFO> Retries %d: source `%s` >> target `%s`", r.Retries, r.SourceURL, r.TargetURL)
    41  }
    42  
    43  func (r retryMessage) JSON() string {
    44  	jsonMessageBytes, e := json.MarshalIndent(r, "", " ")
    45  	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
    46  	return string(jsonMessageBytes)
    47  }
    48  
    49  func (r *retryManager) retry(action func(rm *retryManager) *probe.Error) {
    50  	defer r.cancelRetry()
    51  	for r.retries <= r.maxRetries {
    52  
    53  		err := action(r)
    54  		if err == nil {
    55  			return
    56  		}
    57  
    58  		select {
    59  		case <-r.retryCtx.Done():
    60  			return
    61  		case <-r.commandCtx.Done():
    62  			return
    63  		case <-time.After(r.retryInterval/2 + time.Duration(rand.Int63n(int64(r.retryInterval)))):
    64  			r.retries++
    65  		}
    66  
    67  	}
    68  }