Skip to content

Commit efaffad

Browse files
authored
[Storage] Retry wrapped IOExceptions. (#22647)
* Retry wrapped IOExceptions. * pr feedback.
1 parent 1fdd82f commit efaffad

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/RequestRetryTestFactory.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ class RequestRetryTestFactory {
4949

5050
static final int RETRY_TEST_SCENARIO_NON_REPLAYABLE_FLOWABLE = 9;
5151

52+
static final int RETRY_TEST_SCENARIO_WRAPPED_NETWORK_ERROR = 10;
53+
54+
static final int RETRY_TEST_SCENARIO_WRAPPED_TIMEOUT_ERROR = 11;
55+
5256
// Cancelable
5357

5458
static final String RETRY_TEST_PRIMARY_HOST = "PrimaryDC";
@@ -284,6 +288,30 @@ public Mono<HttpResponse> send(HttpRequest request) {
284288
throw new IllegalArgumentException("Continued retrying after success.");
285289
}
286290

291+
case RETRY_TEST_SCENARIO_WRAPPED_NETWORK_ERROR:
292+
switch (this.factory.tryNumber) {
293+
case 1:
294+
// fall through
295+
case 2:
296+
return Mono.error(Exceptions.propagate(new IOException()));
297+
case 3:
298+
return retryTestOkResponse;
299+
default:
300+
throw new IllegalArgumentException("Continued retrying after success.");
301+
}
302+
303+
case RETRY_TEST_SCENARIO_WRAPPED_TIMEOUT_ERROR:
304+
switch (this.factory.tryNumber) {
305+
case 1:
306+
// fall through
307+
case 2:
308+
return Mono.error(Exceptions.propagate(new TimeoutException()));
309+
case 3:
310+
return retryTestOkResponse;
311+
default:
312+
throw new IllegalArgumentException("Continued retrying after success.");
313+
}
314+
287315
case RETRY_TEST_SCENARIO_TRY_TIMEOUT:
288316
switch (this.factory.tryNumber) {
289317
case 1:

sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/RetryTest.groovy

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import com.azure.storage.common.policy.RetryPolicyType
99
import reactor.core.publisher.Mono
1010
import reactor.test.StepVerifier
1111
import spock.lang.Retry
12+
import spock.lang.Specification
1213
import spock.lang.Unroll
1314

1415
// Tests for package-private functionality.
1516
@Retry(count = 3, delay = 1000)
16-
class RetryTest extends APISpec {
17+
class RetryTest extends Specification {
1718
static URL retryTestURL = new URL("https://" + RequestRetryTestFactory.RETRY_TEST_PRIMARY_HOST)
1819
static RequestRetryOptions retryTestOptions = new RequestRetryOptions(RetryPolicyType.EXPONENTIAL, 6, 2,
1920
1000L, 4000L, RequestRetryTestFactory.RETRY_TEST_SECONDARY_HOST)
@@ -93,6 +94,36 @@ class RetryTest extends APISpec {
9394
}).verifyComplete()
9495
}
9596

97+
def "Retries wrapped network error"() {
98+
setup:
99+
RequestRetryTestFactory retryTestFactory = new RequestRetryTestFactory(RequestRetryTestFactory.RETRY_TEST_SCENARIO_WRAPPED_NETWORK_ERROR, retryTestOptions)
100+
101+
when:
102+
def responseMono = Mono.defer { retryTestFactory.send(retryTestURL) }
103+
104+
then:
105+
StepVerifier.create(responseMono)
106+
.assertNext({
107+
assert it.getStatusCode() == 200
108+
assert retryTestFactory.getTryNumber() == 3
109+
}).verifyComplete()
110+
}
111+
112+
def "Retries wrapped timeout error"() {
113+
setup:
114+
RequestRetryTestFactory retryTestFactory = new RequestRetryTestFactory(RequestRetryTestFactory.RETRY_TEST_SCENARIO_WRAPPED_TIMEOUT_ERROR, retryTestOptions)
115+
116+
when:
117+
def responseMono = Mono.defer { retryTestFactory.send(retryTestURL) }
118+
119+
then:
120+
StepVerifier.create(responseMono)
121+
.assertNext({
122+
assert it.getStatusCode() == 200
123+
assert retryTestFactory.getTryNumber() == 3
124+
}).verifyComplete()
125+
}
126+
96127
def "Retries try timeout"() {
97128
setup:
98129
RequestRetryTestFactory retryTestFactory = new RequestRetryTestFactory(RequestRetryTestFactory.RETRY_TEST_SCENARIO_TRY_TIMEOUT, retryTestOptions)

sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.azure.core.http.policy.HttpLoggingPolicy;
1313
import com.azure.core.http.policy.HttpPipelinePolicy;
1414
import com.azure.core.util.UrlBuilder;
15+
import reactor.core.Exceptions;
1516
import reactor.core.publisher.Flux;
1617
import reactor.core.publisher.Mono;
1718

@@ -181,9 +182,10 @@ we do not consider the secondary at all (considerSecondary==false)). This will
181182
A Timeout Exception is a client-side timeout coming from Rx.
182183
*/
183184
String action;
184-
if (throwable instanceof IOException) {
185+
Throwable unwrappedThrowable = Exceptions.unwrap(throwable);
186+
if (unwrappedThrowable instanceof IOException) {
185187
action = "Retry: Network error";
186-
} else if (throwable instanceof TimeoutException) {
188+
} else if (unwrappedThrowable instanceof TimeoutException) {
187189
action = "Retry: Client timeout";
188190
} else {
189191
action = "NoRetry: Unknown error";

0 commit comments

Comments
 (0)