Merge pull request #1 from garyrussell/AMQP-226
* AMQP-226: AMQP-226 Fix Exponential Back Off
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
* Copyright 2006-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.retry.backoff;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -35,9 +37,11 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Dave Syer
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class ExponentialBackOffPolicy implements BackOffPolicy {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
/**
|
||||
* The default 'initialInterval' value - 100 millisecs. Coupled with the
|
||||
* default 'multiplier' value this gives a useful initial spread of pauses
|
||||
@@ -151,7 +155,11 @@ public class ExponentialBackOffPolicy implements BackOffPolicy {
|
||||
public void backOff(BackOffContext backOffContext) throws BackOffInterruptedException {
|
||||
ExponentialBackOffContext context = (ExponentialBackOffContext) backOffContext;
|
||||
try {
|
||||
sleeper.sleep(context.getSleepAndIncrement());
|
||||
long sleepTime = context.getSleepAndIncrement();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Sleeping for " + sleepTime);
|
||||
}
|
||||
sleeper.sleep(sleepTime);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new BackOffInterruptedException("Thread interrupted while sleeping", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
* Copyright 2006-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.AttributeAccessor;
|
||||
import org.springframework.retry.ExhaustedRetryException;
|
||||
import org.springframework.retry.RecoveryCallback;
|
||||
import org.springframework.retry.RetryCallback;
|
||||
@@ -67,6 +68,7 @@ import org.springframework.retry.policy.SimpleRetryPolicy;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Dave Syer
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class RetryTemplate implements RetryOperations {
|
||||
|
||||
@@ -220,8 +222,22 @@ public class RetryTemplate implements RetryOperations {
|
||||
throw new TerminatedRetryException("Retry terminated abnormally by interceptor before first attempt");
|
||||
}
|
||||
|
||||
// Start the backoff context...
|
||||
BackOffContext backOffContext = backOffPolicy.start(context);
|
||||
// Get or Start the backoff context...
|
||||
BackOffContext backOffContext = null;
|
||||
AttributeAccessor attributeAccessor = null;
|
||||
if (context instanceof AttributeAccessor) {
|
||||
attributeAccessor = (AttributeAccessor) context;
|
||||
Object resource = attributeAccessor.getAttribute("backOffContext");
|
||||
if (resource instanceof BackOffContext) {
|
||||
backOffContext = (BackOffContext) resource;
|
||||
}
|
||||
}
|
||||
if (backOffContext == null) {
|
||||
backOffContext = backOffPolicy.start(context);
|
||||
if (attributeAccessor != null && backOffContext != null) {
|
||||
attributeAccessor.setAttribute("backOffContext", backOffContext);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We allow the whole loop to be skipped if the policy or context
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
* Copyright 2006-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,18 +22,23 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.retry.ExhaustedRetryException;
|
||||
import org.springframework.retry.RecoveryCallback;
|
||||
import org.springframework.retry.RetryCallback;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryState;
|
||||
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
|
||||
import org.springframework.retry.support.DefaultRetryState;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class StatefulRetryIntegrationTests {
|
||||
@@ -114,6 +119,38 @@ public class StatefulRetryIntegrationTests {
|
||||
assertEquals("bar", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExponentialBackOffIsExponential() throws Exception {
|
||||
ExponentialBackOffPolicy policy = new ExponentialBackOffPolicy();
|
||||
policy.setInitialInterval(100);
|
||||
policy.setMultiplier(1.5);
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
template.setBackOffPolicy(policy);
|
||||
final List<Long> times = new ArrayList<Long>();
|
||||
RetryState retryState = new DefaultRetryState("bar");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
template.execute(new RetryCallback<String>() {
|
||||
public String doWithRetry(RetryContext context) throws Exception {
|
||||
times.add(System.currentTimeMillis());
|
||||
throw new Exception("Fail");
|
||||
}
|
||||
}, new RecoveryCallback<String>() {
|
||||
public String recover(RetryContext context)
|
||||
throws Exception {
|
||||
return null;
|
||||
}
|
||||
}, retryState);
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e.getMessage().equals("Fail"));
|
||||
}
|
||||
}
|
||||
assertEquals(3, times.size());
|
||||
assertTrue(times.get(1) - times.get(0) >= 100);
|
||||
assertTrue(times.get(2) - times.get(1) >= 150);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user