Moves incrementing retry_iteration attr from apply to doOnSuccessOrError of filter chain.

The retry_iteration attr only got incremented on a apply, it is not incremented on each iteration of the filter chain.

fixes gh-339
This commit is contained in:
Spencer Gibb
2018-06-08 15:03:58 -04:00
parent 2a48bd0d83
commit e72fb8ab80
2 changed files with 30 additions and 7 deletions

View File

@@ -41,6 +41,8 @@ import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<RetryGatewayFilterFactory.RetryConfig> {
public static final String RETRY_ITERATION_KEY = "retry_iteration";
private static final Log log = LogFactory.getLog(RetryGatewayFilterFactory.class);
public RetryGatewayFilterFactory() {
@@ -51,7 +53,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
public GatewayFilter apply(RetryConfig retryConfig) {
retryConfig.validate();
Predicate<? super RepeatContext<ServerWebExchange>> predicate = context -> {
Predicate<RepeatContext<ServerWebExchange>> repeatPredicate = context -> {
ServerWebExchange exchange = context.applicationContext();
if (exceedsMaxIterations(exchange, retryConfig)) {
return false;
@@ -72,7 +74,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
return retryableMethod && retryableStatusCode;
};
Repeat<ServerWebExchange> repeat = Repeat.onlyIf(predicate)
Repeat<ServerWebExchange> repeat = Repeat.onlyIf(repeatPredicate)
.doOnRepeat(context -> reset(context.applicationContext()));
//TODO: support timeout, backoff, jitter, etc... in Builder
@@ -97,7 +99,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
}
public boolean exceedsMaxIterations(ServerWebExchange exchange, RetryConfig retryConfig) {
Integer iteration = exchange.getAttribute("retry_iteration");
Integer iteration = exchange.getAttribute(RETRY_ITERATION_KEY);
//TODO: deal with null iteration
return iteration != null && iteration >= retryConfig.getRetries();
@@ -117,10 +119,11 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
return (exchange, chain) -> {
log.trace("Entering retry-filter");
int iteration = exchange.getAttributeOrDefault("retry_iteration", -1);
exchange.getAttributes().put("retry_iteration", iteration + 1);
return Mono.fromDirect(chain.filter(exchange)
.doOnSuccessOrError((aVoid, throwable) -> {
int iteration = exchange.getAttributeOrDefault(RETRY_ITERATION_KEY, -1);
exchange.getAttributes().put(RETRY_ITERATION_KEY, iteration + 1);
})
.log("retry-filter", Level.INFO)
.retryWhen(retry.withApplicationContext(exchange))
.repeatWhen(repeat.withApplicationContext(exchange)));

View File

@@ -53,7 +53,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@DirtiesContext
public class RetryConfigGatewayFilterFactoryIntegrationTests extends BaseWebClientTests {
public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTests {
@Test
public void retryFilterGet() {
@@ -64,6 +64,18 @@ public class RetryConfigGatewayFilterFactoryIntegrationTests extends BaseWebClie
.expectBody(String.class).isEqualTo("3");
}
@Test
public void retryFilterFailure() {
testClient.get()
.uri("/retryalwaysfail?key=getjavafailure&count=4")
.header(HttpHeaders.HOST, "www.retryjava.org")
.exchange()
.expectStatus().is5xxServerError()
.expectBody(String.class).consumeWith(result -> {
assertThat(result.getResponseBody()).contains("permanently broken");
});
}
@Test
public void retryFilterGetJavaDsl() {
testClient.get()
@@ -115,6 +127,14 @@ public class RetryConfigGatewayFilterFactoryIntegrationTests extends BaseWebClie
ConcurrentHashMap<String, AtomicInteger> map = new ConcurrentHashMap<>();
@RequestMapping("/httpbin/retryalwaysfail")
public String retryalwaysfail(@RequestParam("key") String key, @RequestParam(name = "count", defaultValue = "3") int count) {
AtomicInteger num = map.computeIfAbsent(key, s -> new AtomicInteger());
int i = num.incrementAndGet();
log.warn("Retry count: "+i);
throw new RuntimeException("permanently broken");
}
@RequestMapping("/httpbin/retry")
public String retry(@RequestParam("key") String key, @RequestParam(name = "count", defaultValue = "3") int count) {
AtomicInteger num = map.computeIfAbsent(key, s -> new AtomicInteger());