1515import java .util .logging .Logger ;
1616
1717public class BoxAPIRequest {
18- private static final Logger LOGGER = Logger .getLogger (BoxFolder .class .getName ());
19- private static final int MAX_BACKOFF_MILLISECONDS = 60000 ;
20- private static final int INITIAL_BACKOFF_EXPONENT = 10 ;
18+ private static final Logger LOGGER = Logger .getLogger (BoxAPIRequest .class .getName ());
2119
2220 private final BoxAPIConnection api ;
2321 private final URL url ;
2422 private final List <RequestHeader > headers ;
2523 private final String method ;
2624
25+ private BackoffCounter backoffCounter ;
2726 private int timeout ;
2827 private InputStream body ;
2928 private long bodyLength ;
@@ -38,6 +37,7 @@ public BoxAPIRequest(BoxAPIConnection api, URL url, String method) {
3837 this .url = url ;
3938 this .method = method ;
4039 this .headers = new ArrayList <RequestHeader >();
40+ this .backoffCounter = new BackoffCounter (new Time ());
4141
4242 this .addHeader ("Accept-Encoding" , "gzip" );
4343 this .addHeader ("Accept-Charset" , "utf-8" );
@@ -66,10 +66,35 @@ public void setBody(String body) {
6666
6767 public BoxAPIResponse send () {
6868 if (this .api == null ) {
69- return this .send (BoxAPIConnection .DEFAULT_MAX_ATTEMPTS , INITIAL_BACKOFF_EXPONENT );
69+ this .backoffCounter . reset (BoxAPIConnection .DEFAULT_MAX_ATTEMPTS );
7070 } else {
71- return this .send (this .api .getMaxAttempts (), INITIAL_BACKOFF_EXPONENT );
71+ this .backoffCounter . reset (this .api .getMaxAttempts ());
7272 }
73+
74+ while (this .backoffCounter .getAttemptsRemaining () > 0 ) {
75+ try {
76+ return this .trySend ();
77+ } catch (BoxAPIException apiException ) {
78+ if (!this .backoffCounter .decrement () || !isResponseRetryable (apiException .getResponseCode ())) {
79+ throw apiException ;
80+ }
81+
82+ try {
83+ this .resetBody ();
84+ } catch (IOException ioException ) {
85+ throw apiException ;
86+ }
87+
88+ try {
89+ this .backoffCounter .waitBackoff ();
90+ } catch (InterruptedException interruptedException ) {
91+ Thread .currentThread ().interrupt ();
92+ throw apiException ;
93+ }
94+ }
95+ }
96+
97+ throw new RuntimeException ();
7398 }
7499
75100 @ Override
@@ -101,6 +126,10 @@ public String toString() {
101126 return builder .toString ();
102127 }
103128
129+ void setBackoffCounter (BackoffCounter counter ) {
130+ this .backoffCounter = counter ;
131+ }
132+
104133 protected String bodyToString () {
105134 return null ;
106135 }
@@ -130,46 +159,6 @@ protected void resetBody() throws IOException {
130159 }
131160 }
132161
133- private BoxAPIResponse send (int maxAttempts , int backoffExp ) {
134- BoxAPIResponse response = null ;
135- try {
136- response = this .trySend ();
137- } catch (BoxAPIException apiException ) {
138- int remainingAttempts = (maxAttempts - 1 );
139- if (remainingAttempts <= 0 || !isResponseRetryable (apiException .getResponseCode ())) {
140- throw apiException ;
141- }
142-
143- int backoffMilliseconds = 2 << backoffExp ;
144- int nextBackoffExp ;
145- if (MAX_BACKOFF_MILLISECONDS < backoffMilliseconds ) {
146- backoffMilliseconds = MAX_BACKOFF_MILLISECONDS ;
147- nextBackoffExp = backoffExp ;
148- } else {
149- nextBackoffExp = backoffExp + 1 ;
150- }
151-
152- try {
153- this .resetBody ();
154- } catch (IOException ioException ) {
155- throw apiException ;
156- }
157-
158- LOGGER .log (Level .WARNING , String .format ("Waiting %d seconds before retrying %d more time(s)." ,
159- (backoffMilliseconds / 1000 ), remainingAttempts ));
160- try {
161- Thread .sleep (backoffMilliseconds );
162- } catch (InterruptedException interruptedException ) {
163- Thread .currentThread ().interrupt ();
164- throw apiException ;
165- }
166-
167- this .send (remainingAttempts , nextBackoffExp );
168- }
169-
170- return response ;
171- }
172-
173162 private BoxAPIResponse trySend () {
174163 HttpURLConnection connection = this .createConnection ();
175164 if (this .bodyLength > 0 ) {
0 commit comments