@@ -548,18 +548,14 @@ func (r Request) finalURLTemplate() url.URL {
548
548
return * url
549
549
}
550
550
551
- func (r * Request ) tryThrottle () error {
551
+ func (r * Request ) tryThrottle (ctx context. Context ) error {
552
552
if r .rateLimiter == nil {
553
553
return nil
554
554
}
555
555
556
556
now := time .Now ()
557
- var err error
558
- if r .ctx != nil {
559
- err = r .rateLimiter .Wait (r .ctx )
560
- } else {
561
- r .rateLimiter .Accept ()
562
- }
557
+
558
+ err := r .rateLimiter .Wait (ctx )
563
559
564
560
if latency := time .Since (now ); latency > longThrottleLatency {
565
561
klog .V (3 ).Infof ("Throttling request took %v, request: %s:%s" , latency , r .verb , r .URL ().String ())
@@ -571,6 +567,11 @@ func (r *Request) tryThrottle() error {
571
567
// Watch attempts to begin watching the requested location.
572
568
// Returns a watch.Interface, or an error.
573
569
func (r * Request ) Watch () (watch.Interface , error ) {
570
+ ctx := context .Background ()
571
+ if r .ctx != nil {
572
+ ctx = r .ctx
573
+ }
574
+
574
575
// We specifically don't want to rate limit watches, so we
575
576
// don't use r.rateLimiter here.
576
577
if r .err != nil {
@@ -582,9 +583,7 @@ func (r *Request) Watch() (watch.Interface, error) {
582
583
if err != nil {
583
584
return nil , err
584
585
}
585
- if r .ctx != nil {
586
- req = req .WithContext (r .ctx )
587
- }
586
+ req = req .WithContext (ctx )
588
587
req .Header = r .headers
589
588
client := r .c .Client
590
589
if client == nil {
@@ -660,11 +659,16 @@ func updateURLMetrics(req *Request, resp *http.Response, err error) {
660
659
// Any non-2xx http status code causes an error. If we get a non-2xx code, we try to convert the body into an APIStatus object.
661
660
// If we can, we return that as an error. Otherwise, we create an error that lists the http status and the content of the response.
662
661
func (r * Request ) Stream () (io.ReadCloser , error ) {
662
+ ctx := context .Background ()
663
+ if r .ctx != nil {
664
+ ctx = r .ctx
665
+ }
666
+
663
667
if r .err != nil {
664
668
return nil , r .err
665
669
}
666
670
667
- if err := r .tryThrottle (); err != nil {
671
+ if err := r .tryThrottle (ctx ); err != nil {
668
672
return nil , err
669
673
}
670
674
@@ -676,9 +680,7 @@ func (r *Request) Stream() (io.ReadCloser, error) {
676
680
if r .body != nil {
677
681
req .Body = ioutil .NopCloser (r .body )
678
682
}
679
- if r .ctx != nil {
680
- req = req .WithContext (r .ctx )
681
- }
683
+ req = req .WithContext (ctx )
682
684
req .Header = r .headers
683
685
client := r .c .Client
684
686
if client == nil {
@@ -746,7 +748,7 @@ func (r *Request) requestPreflightCheck() error {
746
748
// received. It handles retry behavior and up front validation of requests. It will invoke
747
749
// fn at most once. It will return an error if a problem occurred prior to connecting to the
748
750
// server - the provided function is responsible for handling server errors.
749
- func (r * Request ) request (fn func (* http.Request , * http.Response )) error {
751
+ func (r * Request ) request (ctx context. Context , fn func (* http.Request , * http.Response )) error {
750
752
//Metrics for total request latency
751
753
start := time .Now ()
752
754
defer func () {
@@ -767,6 +769,19 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
767
769
client = http .DefaultClient
768
770
}
769
771
772
+ // Throttle the first try before setting up the timeout configured on the
773
+ // client. We don't want a throttled client to return timeouts to callers
774
+ // before it makes a single request.
775
+ if err := r .tryThrottle (ctx ); err != nil {
776
+ return err
777
+ }
778
+
779
+ if r .timeout > 0 {
780
+ var cancel context.CancelFunc
781
+ ctx , cancel = context .WithTimeout (ctx , r .timeout )
782
+ defer cancel ()
783
+ }
784
+
770
785
// Right now we make about ten retry attempts if we get a Retry-After response.
771
786
maxRetries := 10
772
787
retries := 0
@@ -776,25 +791,15 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
776
791
if err != nil {
777
792
return err
778
793
}
779
- if r .timeout > 0 {
780
- if r .ctx == nil {
781
- r .ctx = context .Background ()
782
- }
783
- var cancelFn context.CancelFunc
784
- r .ctx , cancelFn = context .WithTimeout (r .ctx , r .timeout )
785
- defer cancelFn ()
786
- }
787
- if r .ctx != nil {
788
- req = req .WithContext (r .ctx )
789
- }
794
+ req = req .WithContext (ctx )
790
795
req .Header = r .headers
791
796
792
797
r .backoff .Sleep (r .backoff .CalculateBackoff (r .URL ()))
793
798
if retries > 0 {
794
799
// We are retrying the request that we already send to apiserver
795
800
// at least once before.
796
801
// This request should also be throttled with the client-internal rate limiter.
797
- if err := r .tryThrottle (); err != nil {
802
+ if err := r .tryThrottle (ctx ); err != nil {
798
803
return err
799
804
}
800
805
}
@@ -870,12 +875,13 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
870
875
// * If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
871
876
// * http.Client.Do errors are returned directly.
872
877
func (r * Request ) Do () Result {
873
- if err := r .tryThrottle (); err != nil {
874
- return Result {err : err }
878
+ ctx := context .Background ()
879
+ if r .ctx != nil {
880
+ ctx = r .ctx
875
881
}
876
882
877
883
var result Result
878
- err := r .request (func (req * http.Request , resp * http.Response ) {
884
+ err := r .request (ctx , func (req * http.Request , resp * http.Response ) {
879
885
result = r .transformResponse (resp , req )
880
886
})
881
887
if err != nil {
@@ -886,12 +892,13 @@ func (r *Request) Do() Result {
886
892
887
893
// DoRaw executes the request but does not process the response body.
888
894
func (r * Request ) DoRaw () ([]byte , error ) {
889
- if err := r .tryThrottle (); err != nil {
890
- return nil , err
895
+ ctx := context .Background ()
896
+ if r .ctx != nil {
897
+ ctx = r .ctx
891
898
}
892
899
893
900
var result Result
894
- err := r .request (func (req * http.Request , resp * http.Response ) {
901
+ err := r .request (ctx , func (req * http.Request , resp * http.Response ) {
895
902
result .body , result .err = ioutil .ReadAll (resp .Body )
896
903
glogBody ("Response Body" , result .body )
897
904
if resp .StatusCode < http .StatusOK || resp .StatusCode > http .StatusPartialContent {
0 commit comments