@@ -663,6 +663,60 @@ func (r *Request) Do(ctx ...context.Context) *Response {
663663 return resp
664664}
665665
666+ func (r * Request ) shouldRetry (resp * Response , err error ) bool {
667+ if errors .Is (err , context .Canceled ) || r .retryOption == nil ||
668+ (r .RetryAttempt >= r .retryOption .MaxRetries && r .retryOption .MaxRetries >= 0 ) {
669+ return false
670+ }
671+ needRetry := err != nil
672+ if l := len (r .retryOption .RetryConditions ); l > 0 {
673+ for i := l - 1 ; i >= 0 ; i -- {
674+ needRetry = r .retryOption .RetryConditions [i ](resp , err )
675+ if needRetry {
676+ break
677+ }
678+ }
679+ }
680+ return needRetry
681+ }
682+
683+ func (r * Request ) prepareRetry (resp * Response , err error ) {
684+ r .RetryAttempt ++
685+ if l := len (r .retryOption .RetryHooks ); l > 0 {
686+ for i := l - 1 ; i >= 0 ; i -- {
687+ r .retryOption .RetryHooks [i ](resp , err )
688+ }
689+ }
690+ time .Sleep (r .retryOption .GetRetryInterval (resp , r .RetryAttempt ))
691+
692+ if r .dumpBuffer != nil {
693+ r .dumpBuffer .Reset ()
694+ }
695+ if r .trace != nil {
696+ r .trace = & clientTrace {}
697+ }
698+ if resp != nil {
699+ resp .body = nil
700+ resp .result = nil
701+ resp .error = nil
702+ }
703+ }
704+
705+ // tryRetry attempts retry after an error. Returns true if the request loop should continue.
706+ func (r * Request ) tryRetry (resp * * Response , err error ) bool {
707+ if * resp == nil {
708+ * resp = & Response {Request : r }
709+ }
710+ if err != nil {
711+ (* resp ).Err = err
712+ }
713+ if ! r .shouldRetry (* resp , err ) {
714+ return false
715+ }
716+ r .prepareRetry (* resp , err )
717+ return true
718+ }
719+
666720func (r * Request ) do () (resp * Response , err error ) {
667721 defer func () {
668722 if resp == nil {
@@ -673,12 +727,16 @@ func (r *Request) do() (resp *Response, err error) {
673727 }
674728 }()
675729
730+ retry:
676731 for {
677732 if r .Headers == nil {
678733 r .Headers = make (http.Header )
679734 }
680735 for _ , f := range r .client .udBeforeRequest {
681736 if err = f (r .client , r ); err != nil {
737+ if r .tryRetry (& resp , err ) {
738+ continue retry
739+ }
682740 return
683741 }
684742 }
@@ -704,43 +762,12 @@ func (r *Request) do() (resp *Response, err error) {
704762 }
705763 }
706764
707- if contextCanceled || r . retryOption == nil || ( r . RetryAttempt >= r . retryOption . MaxRetries && r . retryOption . MaxRetries >= 0 ) { // absolutely cannot retry.
765+ if contextCanceled {
708766 return
709767 }
710-
711- // check retry whether is needed.
712- needRetry := err != nil // default behaviour: retry if error occurs
713- if l := len (r .retryOption .RetryConditions ); l > 0 { // override default behaviour if custom RetryConditions has been set.
714- for i := l - 1 ; i >= 0 ; i -- {
715- needRetry = r .retryOption .RetryConditions [i ](resp , err )
716- if needRetry {
717- break
718- }
719- }
720- }
721- if ! needRetry { // no retry is needed.
768+ if ! r .tryRetry (& resp , err ) {
722769 return
723770 }
724-
725- // need retry, attempt to retry
726- r .RetryAttempt ++
727- if l := len (r .retryOption .RetryHooks ); l > 0 {
728- for i := l - 1 ; i >= 0 ; i -- { // run retry hooks in reverse order
729- r .retryOption .RetryHooks [i ](resp , err )
730- }
731- }
732- time .Sleep (r .retryOption .GetRetryInterval (resp , r .RetryAttempt ))
733-
734- // clean up before retry
735- if r .dumpBuffer != nil {
736- r .dumpBuffer .Reset ()
737- }
738- if r .trace != nil {
739- r .trace = & clientTrace {}
740- }
741- resp .body = nil
742- resp .result = nil
743- resp .error = nil
744771 }
745772}
746773
0 commit comments