github.com/nilium/gitlab-runner@v12.5.0+incompatible/commands/helpers/retry_helper.go (about)

     1  package helpers
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"time"
     7  
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  type retryHelper struct {
    12  	Retry     int           `long:"retry" description:"How many times to retry upload"`
    13  	RetryTime time.Duration `long:"retry-time" description:"How long to wait between retries"`
    14  }
    15  
    16  // retryableErr indicates that an error can be retried. To specify that an error
    17  // can be retried simply wrap the original error. For example:
    18  //
    19  // retryableErr{err: errors.New("some error")}
    20  type retryableErr struct {
    21  	err error
    22  }
    23  
    24  func (e retryableErr) Error() string {
    25  	return e.err.Error()
    26  }
    27  
    28  func (r *retryHelper) doRetry(handler func() error) error {
    29  	err := handler()
    30  
    31  	for i := 0; i < r.Retry; i++ {
    32  		if _, ok := err.(retryableErr); !ok {
    33  			return err
    34  		}
    35  
    36  		time.Sleep(r.RetryTime)
    37  		logrus.WithError(err).Warningln("Retrying...")
    38  
    39  		err = handler()
    40  	}
    41  
    42  	return err
    43  }
    44  
    45  // retryOnServerError will take the response and check if the the error should
    46  // be of type retryableErr or not. When the status code is of 5xx it will be a
    47  // retryableErr.
    48  func retryOnServerError(resp *http.Response) error {
    49  	if resp.StatusCode/100 == 2 {
    50  		return nil
    51  	}
    52  
    53  	resp.Body.Close()
    54  
    55  	err := fmt.Errorf("received: %s", resp.Status)
    56  
    57  	if resp.StatusCode/100 == 5 {
    58  		err = retryableErr{err: err}
    59  	}
    60  
    61  	return err
    62  }