diff options
author | Niall Sheridan <nsheridan@gmail.com> | 2017-04-10 21:18:42 +0100 |
---|---|---|
committer | Niall Sheridan <nsheridan@gmail.com> | 2017-04-10 21:38:33 +0100 |
commit | 30802e07b2d84fbc213b490d3402707dffe60096 (patch) | |
tree | 934aecb8f3582325dfd1aa6652193adac87d00db /vendor/github.com/sethgrid | |
parent | da7638dc112c4c106e8929601b642d2ca4596cba (diff) |
update dependencies
Diffstat (limited to 'vendor/github.com/sethgrid')
-rw-r--r-- | vendor/github.com/sethgrid/pester/main.go | 78 |
1 files changed, 50 insertions, 28 deletions
diff --git a/vendor/github.com/sethgrid/pester/main.go b/vendor/github.com/sethgrid/pester/main.go index 2771a23..4a69791 100644 --- a/vendor/github.com/sethgrid/pester/main.go +++ b/vendor/github.com/sethgrid/pester/main.go @@ -1,7 +1,6 @@ -package pester - -// pester provides additional resiliency over the standard http client methods by +// Package pester provides additional resiliency over the standard http client methods by // allowing you to control concurrency, retries, and a backoff strategy. +package pester import ( "bytes" @@ -9,7 +8,6 @@ import ( "fmt" "io" "io/ioutil" - "math" "math/rand" "net/http" "net/url" @@ -17,6 +15,15 @@ import ( "time" ) +//ErrUnexpectedMethod occurs when an http.Client method is unable to be mapped from a calling method in the pester client +var ErrUnexpectedMethod = errors.New("unexpected client method, must be one of Do, Get, Head, Post, or PostFrom") + +// ErrReadingBody happens when we cannot read the body bytes +var ErrReadingBody = errors.New("error reading body") + +// ErrReadingRequestBody happens when we cannot read the request body bytes +var ErrReadingRequestBody = errors.New("error reading request body") + // Client wraps the http client and exposes all the functionality of the http.Client. // Additionally, Client provides pester specific values for handling resiliency. type Client struct { @@ -33,6 +40,7 @@ type Client struct { MaxRetries int Backoff BackoffStrategy KeepLog bool + LogHook LogHook SuccessReqNum int SuccessRetryNum int @@ -76,6 +84,12 @@ type params struct { data url.Values } +var random *rand.Rand + +func init() { + random = rand.New(rand.NewSource(time.Now().UnixNano())) +} + // New constructs a new DefaultClient with sensible default values func New() *Client { return &Client{ @@ -95,6 +109,10 @@ func NewExtendedClient(hc *http.Client) *Client { return c } +// PrintErrStrategy is used to log attempts as they happen. +// You know, more visible +type LogHook func(e ErrEntry) + // BackoffStrategy is used to determine how long a retry request should wait until attempted type BackoffStrategy func(retry int) time.Duration @@ -108,13 +126,13 @@ func DefaultBackoff(_ int) time.Duration { // ExponentialBackoff returns ever increasing backoffs by a power of 2 func ExponentialBackoff(i int) time.Duration { - return time.Duration(math.Pow(2, float64(i))) * time.Second + return time.Duration(1<<uint(i)) * time.Second } // ExponentialJitterBackoff returns ever increasing backoffs by a power of 2 // with +/- 0-33% to prevent sychronized reuqests. func ExponentialJitterBackoff(i int) time.Duration { - return jitter(int(math.Pow(2, float64(i)))) + return jitter(int(1 << uint(i))) } // LinearBackoff returns increasing durations, each a second longer than the last @@ -134,14 +152,8 @@ func jitter(i int) time.Duration { maxJitter := ms / 3 - rand.Seed(time.Now().Unix()) - jitter := rand.Intn(maxJitter + 1) - - if rand.Intn(2) == 1 { - ms = ms + jitter - } else { - ms = ms - jitter - } + // ms ± rand + ms += random.Intn(2*maxJitter) - maxJitter // a jitter of 0 messes up the time.Tick chan if ms <= 0 { @@ -206,14 +218,14 @@ func (c *Client) pester(p params) (*http.Response, error) { if p.req != nil && p.req.Body != nil { originalRequestBody, err = ioutil.ReadAll(p.req.Body) if err != nil { - return &http.Response{}, errors.New("error reading request body") + return nil, ErrReadingRequestBody } p.req.Body.Close() } if p.body != nil { originalBody, err = ioutil.ReadAll(p.body) if err != nil { - return &http.Response{}, errors.New("error reading body") + return nil, ErrReadingBody } } @@ -238,7 +250,6 @@ func (c *Client) pester(p params) (*http.Response, error) { return default: } - resp := &http.Response{} // rehydrate the body (it is drained each read) if len(originalRequestBody) > 0 { @@ -248,6 +259,7 @@ func (c *Client) pester(p params) (*http.Response, error) { p.body = bytes.NewBuffer(originalBody) } + var resp *http.Response // route the calls switch p.method { case "Do": @@ -260,6 +272,8 @@ func (c *Client) pester(p params) (*http.Response, error) { resp, err = httpClient.Post(p.url, p.bodyType, p.body) case "PostForm": resp, err = httpClient.PostForm(p.url, p.data) + default: + err = ErrUnexpectedMethod } // Early return if we have a valid result @@ -320,14 +334,13 @@ func (c *Client) pester(p params) (*http.Response, error) { } }() - select { - case res := <-resultCh: - c.Lock() - defer c.Unlock() - c.SuccessReqNum = res.req - c.SuccessRetryNum = res.retry - return res.resp, res.err - } + res := <-resultCh + c.Lock() + defer c.Unlock() + c.SuccessReqNum = res.req + c.SuccessRetryNum = res.retry + return res.resp, res.err + } // LogString provides a string representation of the errors the client has seen @@ -336,12 +349,17 @@ func (c *Client) LogString() string { defer c.Unlock() var res string for _, e := range c.ErrLog { - res += fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n", - e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err) + res += c.FormatError(e) } return res } +// Format the Error to human readable string +func (c *Client) FormatError(e ErrEntry) string { + return fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n", + e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err) +} + // LogErrCount is a helper method used primarily for test validation func (c *Client) LogErrCount() int { c.Lock() @@ -358,8 +376,12 @@ func (c *Client) EmbedHTTPClient(hc *http.Client) { func (c *Client) log(e ErrEntry) { if c.KeepLog { c.Lock() + defer c.Unlock() c.ErrLog = append(c.ErrLog, e) - c.Unlock() + } else if c.LogHook != nil { + // NOTE: There is a possibility that Log Printing hook slows it down. + // but the consumer can always do the Job in a go-routine. + c.LogHook(e) } } |