diff --git a/internal/api.go b/internal/api.go index 0569f5dd..0f0009db 100644 --- a/internal/api.go +++ b/internal/api.go @@ -22,7 +22,6 @@ import ( "strconv" "strings" "sync" - "sync/atomic" "time" "github.com/golang/protobuf/proto" @@ -359,6 +358,14 @@ func (c *aeContext) WriteHeader(code int) { } func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + defer func() { + if ctx.Err() == context.DeadlineExceeded { + err = errTimeout + } + }() + apiURL := apiURL(ctx) hreq := &http.Request{ Method: "POST", @@ -373,6 +380,7 @@ func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, er ContentLength: int64(len(body)), Host: apiURL.Host, } + hreq = hreq.WithContext(ctx) c := fromContext(ctx) if c != nil { if info := c.req.Header.Get(dapperHeader); info != "" { @@ -383,21 +391,6 @@ func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, er } } - tr := apiHTTPClient.Transport.(*http.Transport) - - var timedOut int32 // atomic; set to 1 if timed out - t := time.AfterFunc(timeout, func() { - atomic.StoreInt32(&timedOut, 1) - tr.CancelRequest(hreq) - }) - defer t.Stop() - defer func() { - // Check if timeout was exceeded. - if atomic.LoadInt32(&timedOut) != 0 { - err = errTimeout - } - }() - hresp, err := apiHTTPClient.Do(hreq) if err != nil { return nil, &CallError{ diff --git a/internal/api_test.go b/internal/api_test.go index 9692b29e..f95cde4f 100644 --- a/internal/api_test.go +++ b/internal/api_test.go @@ -468,11 +468,11 @@ func TestAPICallAllocations(t *testing.T) { } // Lots of room for improvement... - var min, max float64 = 60, 86 + var min, max float64 = 60, 100 if strings.HasPrefix(runtime.Version(), "go1.11.") || strings.HasPrefix(runtime.Version(), "go1.12.") { // add a bit more overhead for versions before go1.13 // see https://go.dev/doc/go1.13#compilers - max = 90 + max += 10 } if avg < min || max < avg { t.Errorf("Allocations per API call = %g, want in [%g,%g]", avg, min, max) diff --git a/v2/internal/api.go b/v2/internal/api.go index 44314a2b..9ccdd261 100644 --- a/v2/internal/api.go +++ b/v2/internal/api.go @@ -17,7 +17,6 @@ import ( "os" "runtime" "strconv" - "sync/atomic" "time" "github.com/golang/protobuf/proto" @@ -315,6 +314,14 @@ func (c *aeContext) WriteHeader(code int) { } func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + defer func() { + if ctx.Err() == context.DeadlineExceeded { + err = errTimeout + } + }() + apiURL := apiURL(ctx) hreq := &http.Request{ Method: "POST", @@ -329,6 +336,7 @@ func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, er ContentLength: int64(len(body)), Host: apiURL.Host, } + hreq = hreq.WithContext(ctx) c := fromContext(ctx) if c != nil { if info := c.req.Header.Get(dapperHeader); info != "" { @@ -339,21 +347,6 @@ func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, er } } - tr := apiHTTPClient.Transport.(*http.Transport) - - var timedOut int32 // atomic; set to 1 if timed out - t := time.AfterFunc(timeout, func() { - atomic.StoreInt32(&timedOut, 1) - tr.CancelRequest(hreq) - }) - defer t.Stop() - defer func() { - // Check if timeout was exceeded. - if atomic.LoadInt32(&timedOut) != 0 { - err = errTimeout - } - }() - hresp, err := apiHTTPClient.Do(hreq) if err != nil { return nil, &CallError{ diff --git a/v2/internal/api_test.go b/v2/internal/api_test.go index 073e9bfd..0979dea4 100644 --- a/v2/internal/api_test.go +++ b/v2/internal/api_test.go @@ -324,7 +324,7 @@ func TestAPICallAllocations(t *testing.T) { } // Lots of room for improvement... - const min, max float64 = 60, 86 + const min, max float64 = 60, 100 if avg < min || max < avg { t.Errorf("Allocations per API call = %g, want in [%g,%g]", avg, min, max) }