From a7cd913d999a0528368d1afd9e70de07f7c467af Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Fri, 15 Sep 2023 23:50:19 +0200 Subject: [PATCH] Fix bad Next behaviour (#53) --- hedged.go | 6 ++++- hedged_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/hedged.go b/hedged.go index 0852224..b7b33f5 100644 --- a/hedged.go +++ b/hedged.go @@ -174,9 +174,13 @@ func (ht *hedgedTransport) RoundTrip(req *http.Request) (*http.Response, error) } // no hedged requests, just a regular one. - if upto == 0 { + if upto <= 0 { return ht.rt.RoundTrip(req) } + // rollback to default timeout. + if timeout < 0 { + timeout = ht.timeout + } errOverall := &MultiError{} resultCh := make(chan indexedResp, upto) diff --git a/hedged_test.go b/hedged_test.go index c5ae939..77cf1f5 100644 --- a/hedged_test.go +++ b/hedged_test.go @@ -46,6 +46,66 @@ func TestClient(t *testing.T) { mustTrue(t, took >= handlerSleep && took < (handlerSleep+10*time.Millisecond)) } +func TestClientBadNextUpto(t *testing.T) { + const handlerSleep = 100 * time.Millisecond + url := testServerURL(t, func(w http.ResponseWriter, r *http.Request) { + time.Sleep(handlerSleep) + }) + + cfg := hedgedhttp.Config{ + Transport: http.DefaultTransport, + Upto: 2, + Delay: 50 * time.Millisecond, + Next: func() (upto int, delay time.Duration) { + return -1, 10 * time.Millisecond + }, + } + client, err := hedgedhttp.New(cfg) + mustOk(t, err) + + start := time.Now() + resp, err := client.Do(newGetReq(url)) + took := time.Since(start) + mustOk(t, err) + defer resp.Body.Close() + mustTrue(t, resp != nil) + mustEqual(t, resp.StatusCode, http.StatusOK) + + stats := client.Stats() + mustEqual(t, stats.ActualRoundTrips(), uint64(0)) + mustTrue(t, took >= handlerSleep && took < (handlerSleep+10*time.Millisecond)) +} + +func TestClientBadNextDelay(t *testing.T) { + const handlerSleep = 100 * time.Millisecond + url := testServerURL(t, func(w http.ResponseWriter, r *http.Request) { + time.Sleep(handlerSleep) + }) + + cfg := hedgedhttp.Config{ + Transport: http.DefaultTransport, + Upto: 2, + Delay: 150 * time.Millisecond, + Next: func() (upto int, delay time.Duration) { + return 2, -10 * time.Millisecond + }, + } + client, err := hedgedhttp.New(cfg) + mustOk(t, err) + + start := time.Now() + resp, err := client.Do(newGetReq(url)) + took := time.Since(start) + mustOk(t, err) + defer resp.Body.Close() + mustTrue(t, resp != nil) + mustEqual(t, resp.StatusCode, http.StatusOK) + + stats := client.Stats() + mustEqual(t, stats.ActualRoundTrips(), uint64(1)) + mustTrue(t, took >= handlerSleep && took < (handlerSleep+10*time.Millisecond)) +} + func TestValidateInput(t *testing.T) { var err error _, err = hedgedhttp.New(hedgedhttp.Config{