func TestLinearJitterBackoff(t *testing.T) { t.Parallel() c := pester.New() c.Backoff = pester.LinearJitterBackoff c.KeepLog = true nonExistantURL := "http://localhost:9000/foo" _, err := c.Get(nonExistantURL) if err == nil { t.Fatal("expected to get an error") } // in the event of an error, let's see what the logs were t.Log("\n", c.LogString()) var startTime int64 var delta int64 for i, e := range c.ErrLog { switch i { case 0: startTime = e.Time.Unix() case 1: delta += 1 case 2: delta += 2 case 3: delta += 3 } if got, want := e.Time.Unix(), startTime+delta; withinEpsilon(got, want, 0.0) { t.Errorf("got time %d, want %d (within epsilon of start time %d)", got, want, startTime) } } }
// NewClient create a default client with resilient HTTP client. func NewClient() Client { c := pester.New() c.Timeout = 5 * time.Minute c.MaxRetries = 8 c.Backoff = pester.ExponentialBackoff return Client{doer: c} }
func (m Marathon) getClient() *pester.Client { client := pester.New() client.Transport = &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ InsecureSkipVerify: m.NoVerifySsl, }, } return client }
func TestExponentialBackoff(t *testing.T) { t.Parallel() c := pester.New() c.MaxRetries = 4 c.Backoff = pester.ExponentialBackoff c.KeepLog = true nonExistantURL := "http://localhost:9000/foo" _, err := c.Get(nonExistantURL) if err == nil { t.Fatal("expected to get an error") } // in the event of an error, let's see what the logs were t.Log("\n", c.LogString()) if got, want := len(c.ErrLog), c.MaxRetries; got != want { t.Fatalf("got %d errors, want %d", got, want) } var startTime int64 var delta int64 for i, e := range c.ErrLog { switch i { case 0: startTime = e.Time.Unix() case 1: delta += 1 case 2: delta += 2 case 3: delta += 4 } if got, want := e.Time.Unix(), startTime+delta; got != want { t.Errorf("got time %d, want %d (%d greater than start time %d)", got, want, delta, startTime) } } }
func TestConcurrentRequests(t *testing.T) { t.Parallel() c := pester.New() c.Concurrency = 4 c.KeepLog = true nonExistantURL := "http://localhost:9000/foo" _, err := c.Get(nonExistantURL) if err == nil { t.Fatal("expected to get an error") } // in the event of an error, let's see what the logs were t.Log("\n", c.LogString()) if got, want := len(c.ErrLog), c.Concurrency*c.MaxRetries; got != want { t.Error("got %d attempts, want %d", got, want) } }
func TestDefaultBackoff(t *testing.T) { t.Parallel() c := pester.New() c.KeepLog = true nonExistantURL := "http://localhost:9000/foo" _, err := c.Get(nonExistantURL) if err == nil { t.Fatal("expected to get an error") } // in the event of an error, let's see what the logs were t.Log("\n", c.LogString()) if got, want := c.Concurrency, 1; got != want { t.Error("got %d, want %d for concurrency", got, want) } if got, want := len(c.ErrLog), c.MaxRetries; got != want { t.Fatalf("got %d errors, want %d", got, want) } var startTime int64 for i, e := range c.ErrLog { if i == 0 { startTime = e.Time.Unix() continue } if got, want := e.Time.Unix(), startTime+int64(i); got != want { t.Errorf("got time %d, want %d (%d greater than start time %d)", got, want, i, startTime) } } }
func main() { // set everything up var port int flag.IntVar(&port, "port", 9000, "set the port for the rando response server") flag.Parse() log.Printf("Starting a rando response server on :%d ...\n\n", port) go func() { http.HandleFunc("/", randoHandler) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) }() ////////////////////////////////////////////////////// // begin running through each of the pestor methods // ////////////////////////////////////////////////////// log.Println("> pester.Get default") { // drop in replacement for http.Get and other client methods resp, err := pester.Get(fmt.Sprintf("http://localhost:%d", port)) if err != nil { log.Fatalf("error GETing default", err) } defer resp.Body.Close() log.Printf("GET :%d %s \n\n", port, resp.Status) } log.Println("> pester.Get with set backoff stategy, concurrency and retries increased") { // control the resiliency client := pester.New() client.Concurrency = 3 client.MaxRetries = 5 client.Backoff = pester.ExponentialJitterBackoff client.KeepLog = true resp, err := client.Get(fmt.Sprintf("http://localhost:%d", port)) if err != nil { log.Fatalf("error GETing with all options, %s\n\n", client.LogString()) } defer resp.Body.Close() log.Printf("Exponential Jitter Backoff :%d %s [request %d, retry %d]\n\n", port, resp.Status, client.SuccessReqNum, client.SuccessRetryNum) } log.Println("> pester.Get with custom backoff strategy") { // set a custom backoff strategy client := pester.New() client.Backoff = func(retry int) time.Duration { return time.Duration(retry*200) * time.Millisecond } client.Timeout = 5 * time.Second client.KeepLog = true resp, err := client.Get(fmt.Sprintf("http://localhost:%d", port)) if err != nil { log.Fatalf("error GETing custom backoff\n\n", client.LogString()) } defer resp.Body.Close() log.Printf("Custom backoff :%d %s [request %d, retry %d]\n\n", port, resp.Status, client.SuccessReqNum, client.SuccessRetryNum) } log.Println("> pester.Post with defaults") { // use the pester.Post drop in replacement resp, err := pester.Post(fmt.Sprintf("http://localhost:%d", port), "text/plain", strings.NewReader("data")) if err != nil { log.Fatalf("error POSTing with defaults - %v\n\n", err) } defer resp.Body.Close() log.Printf("POST :%d %s\n\n", port, resp.Status) } log.Println("> pester.Head with defaults") { // use the pester.Head drop in replacement resp, err := pester.Head(fmt.Sprintf("http://localhost:%d", port)) if err != nil { log.Fatalf("error HEADing with defaults - %v\n\n", err) } defer resp.Body.Close() log.Printf("HEAD :%d %s\n\n", port, resp.Status) } log.Println("> pester.PostForm with defaults") { // use the pester.Head drop in replacement resp, err := pester.PostForm(fmt.Sprintf("http://localhost:%d", port), url.Values{"param1": []string{"val1a", "val1b"}, "param2": []string{"val2"}}) if err != nil { log.Fatalf("error POSTing a form with defaults - %v\n\n", err) } defer resp.Body.Close() log.Printf("POST (form) :%d %s\n\n", port, resp.Status) } log.Println("> pester Do with POST") { // use the pester version of http.Client.Do req, err := http.NewRequest("POST", fmt.Sprintf("http://localhost:%d", port), strings.NewReader("data")) if err != nil { log.Fatal("Unable to create a new http request", err) } resp, err := pester.Do(req) if err != nil { log.Fatalf("error POSTing with Do() - %v\n\n", err) } defer resp.Body.Close() log.Printf("Do() POST :%d %s\n\n", port, resp.Status) } }