Make BackOffContext Serializable
This commit is contained in:
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.retry.backoff;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @since 2.1
|
||||
*/
|
||||
public interface BackOffContext {
|
||||
public interface BackOffContext extends Serializable {
|
||||
|
||||
}
|
||||
|
||||
@@ -22,31 +22,29 @@ import org.springframework.retry.RetryContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link BackOffPolicy} that increases the back off period
|
||||
* for each retry attempt in a given set using the {@link Math#exp(double)
|
||||
* exponential} function.
|
||||
* Implementation of {@link BackOffPolicy} that increases the back off period for each
|
||||
* retry attempt in a given set using the {@link Math#exp(double) exponential} function.
|
||||
*
|
||||
* This implementation is thread-safe and suitable for concurrent access.
|
||||
* Modifications to the configuration do not affect any retry sets that are
|
||||
* already in progress.
|
||||
* This implementation is thread-safe and suitable for concurrent access. Modifications to
|
||||
* the configuration do not affect any retry sets that are already in progress.
|
||||
*
|
||||
* The {@link #setInitialInterval(long)} property controls the initial value
|
||||
* passed to {@link Math#exp(double)} and the {@link #setMultiplier(double)}
|
||||
* property controls by how much this value is increased for each subsequent
|
||||
* attempt.
|
||||
* The {@link #setInitialInterval(long)} property controls the initial value passed to
|
||||
* {@link Math#exp(double)} and the {@link #setMultiplier(double)} property controls by
|
||||
* how much this value is increased for each subsequent attempt.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Dave Syer
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<ExponentialBackOffPolicy> {
|
||||
@SuppressWarnings("serial")
|
||||
public class ExponentialBackOffPolicy
|
||||
implements SleepingBackOffPolicy<ExponentialBackOffPolicy> {
|
||||
|
||||
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
|
||||
* for 1-5 retries.
|
||||
* The default 'initialInterval' value - 100 millisecs. Coupled with the default
|
||||
* 'multiplier' value this gives a useful initial spread of pauses for 1-5 retries.
|
||||
*/
|
||||
public static final long DEFAULT_INITIAL_INTERVAL = 100L;
|
||||
|
||||
@@ -85,27 +83,27 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
this.sleeper = sleeper;
|
||||
}
|
||||
|
||||
public ExponentialBackOffPolicy withSleeper(Sleeper sleeper) {
|
||||
ExponentialBackOffPolicy res = newInstance();
|
||||
cloneValues(res);
|
||||
res.setSleeper(sleeper);
|
||||
return res;
|
||||
}
|
||||
public ExponentialBackOffPolicy withSleeper(Sleeper sleeper) {
|
||||
ExponentialBackOffPolicy res = newInstance();
|
||||
cloneValues(res);
|
||||
res.setSleeper(sleeper);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected ExponentialBackOffPolicy newInstance() {
|
||||
return new ExponentialBackOffPolicy();
|
||||
}
|
||||
protected ExponentialBackOffPolicy newInstance() {
|
||||
return new ExponentialBackOffPolicy();
|
||||
}
|
||||
|
||||
protected void cloneValues(ExponentialBackOffPolicy target) {
|
||||
target.setInitialInterval(getInitialInterval());
|
||||
target.setMaxInterval(getMaxInterval());
|
||||
target.setMultiplier(getMultiplier());
|
||||
target.setSleeper(sleeper);
|
||||
}
|
||||
protected void cloneValues(ExponentialBackOffPolicy target) {
|
||||
target.setInitialInterval(getInitialInterval());
|
||||
target.setMaxInterval(getMaxInterval());
|
||||
target.setMultiplier(getMultiplier());
|
||||
target.setSleeper(sleeper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the initial sleep interval value. Default is {@code 100}
|
||||
* millisecond. Cannot be set to a value less than one.
|
||||
* Set the initial sleep interval value. Default is {@code 100} millisecond. Cannot be
|
||||
* set to a value less than one.
|
||||
*
|
||||
* @param initialInterval the initial interval
|
||||
*/
|
||||
@@ -114,9 +112,8 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the multiplier value. Default is '<code>2.0</code>'. Hint: do not use
|
||||
* values much in excess of 1.0 (or the backoff will get very long very
|
||||
* fast).
|
||||
* Set the multiplier value. Default is '<code>2.0</code>'. Hint: do not use values
|
||||
* much in excess of 1.0 (or the backoff will get very long very fast).
|
||||
* @param multiplier the multiplier
|
||||
*/
|
||||
public void setMultiplier(double multiplier) {
|
||||
@@ -124,10 +121,10 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for maximum back off period. Default is 30000 (30 seconds). the
|
||||
* value will be reset to 1 if this method is called with a value less than
|
||||
* 1. Set this to avoid infinite waits if backing off a large number of
|
||||
* times (or if the multiplier is set too high).
|
||||
* Setter for maximum back off period. Default is 30000 (30 seconds). the value will
|
||||
* be reset to 1 if this method is called with a value less than 1. Set this to avoid
|
||||
* infinite waits if backing off a large number of times (or if the multiplier is set
|
||||
* too high).
|
||||
*
|
||||
* @param maxInterval in milliseconds.
|
||||
*/
|
||||
@@ -153,8 +150,7 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
}
|
||||
|
||||
/**
|
||||
* The multiplier to use to generate the next backoff interval from the
|
||||
* last.
|
||||
* The multiplier to use to generate the next backoff interval from the last.
|
||||
*
|
||||
* @return the multiplier in use
|
||||
*/
|
||||
@@ -163,18 +159,19 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of {@link BackOffContext} configured with the
|
||||
* 'expSeed' and 'increment' values.
|
||||
* Returns a new instance of {@link BackOffContext} configured with the 'expSeed' and
|
||||
* 'increment' values.
|
||||
*/
|
||||
public BackOffContext start(RetryContext context) {
|
||||
return new ExponentialBackOffContext(this.initialInterval, this.multiplier, this.maxInterval);
|
||||
return new ExponentialBackOffContext(this.initialInterval, this.multiplier,
|
||||
this.maxInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause for a length of time equal to '
|
||||
* <code>exp(backOffContext.expSeed)</code>'.
|
||||
* Pause for a length of time equal to ' <code>exp(backOffContext.expSeed)</code>'.
|
||||
*/
|
||||
public void backOff(BackOffContext backOffContext) throws BackOffInterruptedException {
|
||||
public void backOff(BackOffContext backOffContext)
|
||||
throws BackOffInterruptedException {
|
||||
ExponentialBackOffContext context = (ExponentialBackOffContext) backOffContext;
|
||||
try {
|
||||
long sleepTime = context.getSleepAndIncrement();
|
||||
@@ -188,7 +185,7 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
}
|
||||
}
|
||||
|
||||
static class ExponentialBackOffContext implements BackOffContext {
|
||||
static class ExponentialBackOffContext implements BackOffContext {
|
||||
|
||||
private final double multiplier;
|
||||
|
||||
@@ -196,43 +193,44 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy<Exponenti
|
||||
|
||||
private long maxInterval;
|
||||
|
||||
public ExponentialBackOffContext(long expSeed, double multiplier, long maxInterval) {
|
||||
public ExponentialBackOffContext(long expSeed, double multiplier,
|
||||
long maxInterval) {
|
||||
this.interval = expSeed;
|
||||
this.multiplier = multiplier;
|
||||
this.maxInterval = maxInterval;
|
||||
}
|
||||
|
||||
public synchronized long getSleepAndIncrement() {
|
||||
long sleep = this.interval;
|
||||
if (sleep > maxInterval) {
|
||||
sleep = maxInterval;
|
||||
}
|
||||
else {
|
||||
this.interval = getNextInterval();
|
||||
}
|
||||
return sleep;
|
||||
}
|
||||
public synchronized long getSleepAndIncrement() {
|
||||
long sleep = this.interval;
|
||||
if (sleep > maxInterval) {
|
||||
sleep = maxInterval;
|
||||
}
|
||||
else {
|
||||
this.interval = getNextInterval();
|
||||
}
|
||||
return sleep;
|
||||
}
|
||||
|
||||
protected long getNextInterval() {
|
||||
return (long)(this.interval * this.multiplier);
|
||||
}
|
||||
protected long getNextInterval() {
|
||||
return (long) (this.interval * this.multiplier);
|
||||
}
|
||||
|
||||
public double getMultiplier() {
|
||||
return multiplier;
|
||||
}
|
||||
public double getMultiplier() {
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
public long getInterval() {
|
||||
return interval;
|
||||
}
|
||||
public long getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
public long getMaxInterval() {
|
||||
return maxInterval;
|
||||
}
|
||||
public long getMaxInterval() {
|
||||
return maxInterval;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ClassUtils.getShortName(getClass()) + "[initialInterval=" + initialInterval + ", multiplier="
|
||||
+ multiplier + ", maxInterval=" + maxInterval + "]";
|
||||
return ClassUtils.getShortName(getClass()) + "[initialInterval=" + initialInterval
|
||||
+ ", multiplier=" + multiplier + ", maxInterval=" + maxInterval + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.util.Random;
|
||||
* @author Jon Travis
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ExponentialRandomBackOffPolicy extends ExponentialBackOffPolicy {
|
||||
/**
|
||||
* Returns a new instance of {@link org.springframework.retry.backoff.BackOffContext},
|
||||
|
||||
@@ -28,4 +28,10 @@ public class NoBackOffPolicy extends StatelessBackOffPolicy {
|
||||
|
||||
protected void doBackOff() throws BackOffInterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NoBackOffPolicy []";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ package org.springframework.retry.backoff;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@Deprecated
|
||||
public class ObjectWaitSleeper implements Sleeper {
|
||||
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package org.springframework.retry.backoff;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Strategy interface for backoff policies to delegate the pausing of execution.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface Sleeper {
|
||||
public interface Sleeper extends Serializable {
|
||||
|
||||
/**
|
||||
* Pause for the specified period using whatever means available.
|
||||
|
||||
@@ -22,6 +22,7 @@ package org.springframework.retry.backoff;
|
||||
* @author Artem Bilan
|
||||
* @since 1.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ThreadWaitSleeper implements Sleeper {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -106,7 +106,8 @@ public class RetrySimulator {
|
||||
static class FailingRetryException extends Exception {
|
||||
}
|
||||
|
||||
static class StealingSleeper implements Sleeper {
|
||||
@SuppressWarnings("serial")
|
||||
static class StealingSleeper implements Sleeper {
|
||||
private final List<Long> sleeps = new ArrayList<Long>();
|
||||
|
||||
public void sleep(long backOffPeriod) throws InterruptedException {
|
||||
|
||||
@@ -171,6 +171,7 @@ public class EnableRetryTests {
|
||||
@EnableRetry
|
||||
protected static class TestConfiguration {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Bean
|
||||
public Sleeper sleeper() {
|
||||
return new Sleeper() {
|
||||
|
||||
@@ -121,6 +121,7 @@ public class EnableRetryWithBackoffTests {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
protected static class PeriodSleeper implements Sleeper {
|
||||
|
||||
private List<Long> periods = new ArrayList<Long>();
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.retry.backoff;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||
import org.springframework.retry.context.RetryContextSupport;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.SerializationUtils;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class BackOffPolicySerializationTests {
|
||||
|
||||
private static Log logger = LogFactory.getLog(BackOffPolicySerializationTests.class);
|
||||
|
||||
private BackOffPolicy policy;
|
||||
|
||||
@Parameters(name = "{index}: {0}")
|
||||
public static List<Object[]> policies() {
|
||||
List<Object[]> result = new ArrayList<Object[]>();
|
||||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(
|
||||
true);
|
||||
scanner.addIncludeFilter(new AssignableTypeFilter(BackOffPolicy.class));
|
||||
scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Test.*")));
|
||||
scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Mock.*")));
|
||||
scanner.addExcludeFilter(
|
||||
new RegexPatternTypeFilter(Pattern.compile(".*Configuration.*")));
|
||||
Set<BeanDefinition> candidates = scanner
|
||||
.findCandidateComponents("org.springframework.retry");
|
||||
for (BeanDefinition beanDefinition : candidates) {
|
||||
try {
|
||||
result.add(new Object[] { BeanUtils.instantiate(ClassUtils
|
||||
.resolveClassName(beanDefinition.getBeanClassName(), null)) });
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn(
|
||||
"Cannot create instance of " + beanDefinition.getBeanClassName());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public BackOffPolicySerializationTests(BackOffPolicy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationCycleForContext() {
|
||||
BackOffContext context = policy.start(new RetryContextSupport(null));
|
||||
if (context != null) {
|
||||
assertTrue(SerializationUtils.deserialize(
|
||||
SerializationUtils.serialize(context)) instanceof BackOffContext);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DummySleeper implements Sleeper {
|
||||
|
||||
private List<Long> backOffs = new ArrayList<Long>();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.retry.policy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -349,6 +349,7 @@ public class RetryTemplateTests {
|
||||
tested.setRetryPolicy(new SimpleRetryPolicy(1));
|
||||
|
||||
BackOffPolicy bop = createStrictMock(BackOffPolicy.class);
|
||||
@SuppressWarnings("serial")
|
||||
BackOffContext backOffContext = new BackOffContext() {
|
||||
};
|
||||
tested.setBackOffPolicy(bop);
|
||||
|
||||
Reference in New Issue
Block a user