From a6aa75bb8d4700309b9ecdc6574b4715504f7433 Mon Sep 17 00:00:00 2001 From: pkupczyk <pkupczyk> Date: Tue, 6 Dec 2011 13:31:06 +0000 Subject: [PATCH] LMS-2675 - InfectX: retry API methods when they fail - make it configurable SVN: 23892 --- .../cisd/common/retry/RetryCaller.java | 74 +++++++++---------- .../config/DefaultRetryConfiguration.java | 53 +++++++++++++ .../retry/config/RetryConfiguration.java | 31 ++++++++ .../config/StaticRetryConfiguration.java | 62 ++++++++++++++++ .../cisd/common/retry/RetryCallerTest.java | 23 ++++-- .../common/retry/RetryProxyFactoryTest.java | 16 ++++ 6 files changed, 214 insertions(+), 45 deletions(-) create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/config/DefaultRetryConfiguration.java create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/config/RetryConfiguration.java create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/config/StaticRetryConfiguration.java diff --git a/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java b/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java index 16483ac04d6..369d95c1e8e 100644 --- a/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java +++ b/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java @@ -18,19 +18,49 @@ package ch.systemsx.cisd.common.retry; import org.springframework.remoting.RemoteConnectFailureException; +import ch.systemsx.cisd.common.retry.config.DefaultRetryConfiguration; +import ch.systemsx.cisd.common.retry.config.RetryConfiguration; + /** * @author pkupczyk */ public abstract class RetryCaller<T, E extends Throwable> { - private int retryCounter = 1; + private RetryConfiguration configuration; - private int retryMaxCounter = 5; + private int retryCounter; - private int retryWaitingTime = 1000; + private int waitingTime; - private int retryWaitingTimeFactor = 2; + public RetryCaller() + { + this(DefaultRetryConfiguration.getInstance()); + } + + public RetryCaller(RetryConfiguration configuration) + { + if (configuration == null) + { + throw new IllegalArgumentException("Configuration was null"); + } + if (configuration.getMaximumNumberOfRetries() < 0) + { + throw new IllegalArgumentException("MaximumNumberOfRetries must be >= 0"); + } + if (configuration.getWaitingTimeBetweenRetries() <= 0) + { + throw new IllegalArgumentException("WaitingTimeBetweenRetries must be > 0"); + } + if (configuration.getWaitingTimeBetweenRetriesIncreasingFactor() <= 0) + { + throw new IllegalArgumentException( + "WaitingTimeBetweenRetriesIncreasingFactor must be > 0"); + } + + this.configuration = configuration; + this.waitingTime = configuration.getWaitingTimeBetweenRetries(); + } protected abstract T call() throws E; @@ -59,15 +89,15 @@ public abstract class RetryCaller<T, E extends Throwable> private boolean shouldRetry() { - return retryCounter < retryMaxCounter; + return retryCounter < configuration.getMaximumNumberOfRetries(); } private void waitForRetry() { try { - Thread.sleep(retryWaitingTime); - retryWaitingTime *= retryWaitingTimeFactor; + Thread.sleep(waitingTime); + waitingTime *= configuration.getWaitingTimeBetweenRetriesIncreasingFactor(); retryCounter++; } catch (InterruptedException e) { @@ -75,34 +105,4 @@ public abstract class RetryCaller<T, E extends Throwable> } } - public int getRetryMaxCounter() - { - return retryMaxCounter; - } - - public void setRetryMaxCounter(int retryMaxCounter) - { - this.retryMaxCounter = retryMaxCounter; - } - - public int getRetryWaitingTime() - { - return retryWaitingTime; - } - - public void setRetryWaitingTime(int retryWaitingTime) - { - this.retryWaitingTime = retryWaitingTime; - } - - public int getRetryWaitingTimeFactor() - { - return retryWaitingTimeFactor; - } - - public void setRetryWaitingTimeFactor(int retryWaitingTimeFactor) - { - this.retryWaitingTimeFactor = retryWaitingTimeFactor; - } - } diff --git a/common/source/java/ch/systemsx/cisd/common/retry/config/DefaultRetryConfiguration.java b/common/source/java/ch/systemsx/cisd/common/retry/config/DefaultRetryConfiguration.java new file mode 100644 index 00000000000..7a8bdf32615 --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/retry/config/DefaultRetryConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.common.retry.config; + +/** + * @author pkupczyk + */ +public class DefaultRetryConfiguration extends StaticRetryConfiguration +{ + + private static final int DEFAULT_NUMBER_OF_RETRIES = 5; + + private static final int DEFAULT_WAITING_TIME_BETWEEN_RETRIES = 1000; + + private static final float DEFAULT_WAITING_TIME_BETWEEN_RETRIES_INCREASING_FACTOR = 2; + + private static final DefaultRetryConfiguration instance = new DefaultRetryConfiguration(); + static + { + instance.reset(); + } + + private DefaultRetryConfiguration() + { + } + + public void reset() + { + instance.setMaximumNumberOfRetries(DEFAULT_NUMBER_OF_RETRIES); + instance.setWaitingTimeBetweenRetries(DEFAULT_WAITING_TIME_BETWEEN_RETRIES); + instance.setWaitingTimeBetweenRetriesIncreasingFactor(DEFAULT_WAITING_TIME_BETWEEN_RETRIES_INCREASING_FACTOR); + } + + public static final DefaultRetryConfiguration getInstance() + { + return instance; + } + +} diff --git a/common/source/java/ch/systemsx/cisd/common/retry/config/RetryConfiguration.java b/common/source/java/ch/systemsx/cisd/common/retry/config/RetryConfiguration.java new file mode 100644 index 00000000000..a85544daee3 --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/retry/config/RetryConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.common.retry.config; + +/** + * @author pkupczyk + */ +public interface RetryConfiguration +{ + + public int getMaximumNumberOfRetries(); + + public int getWaitingTimeBetweenRetries(); + + public float getWaitingTimeBetweenRetriesIncreasingFactor(); + +} diff --git a/common/source/java/ch/systemsx/cisd/common/retry/config/StaticRetryConfiguration.java b/common/source/java/ch/systemsx/cisd/common/retry/config/StaticRetryConfiguration.java new file mode 100644 index 00000000000..d7cd90cbaaf --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/retry/config/StaticRetryConfiguration.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.common.retry.config; + +/** + * @author pkupczyk + */ +public class StaticRetryConfiguration implements RetryConfiguration +{ + + private int maximumNumberOfRetries; + + private int waitingTimeBetweenRetries; + + private float waitingTimeBetweenRetriesIncreasingFactor; + + public int getMaximumNumberOfRetries() + { + return maximumNumberOfRetries; + } + + public void setMaximumNumberOfRetries(int maximumNumberOfRetries) + { + this.maximumNumberOfRetries = maximumNumberOfRetries; + } + + public int getWaitingTimeBetweenRetries() + { + return waitingTimeBetweenRetries; + } + + public void setWaitingTimeBetweenRetries(int waitingTimeBetweenRetries) + { + this.waitingTimeBetweenRetries = waitingTimeBetweenRetries; + } + + public float getWaitingTimeBetweenRetriesIncreasingFactor() + { + return waitingTimeBetweenRetriesIncreasingFactor; + } + + public void setWaitingTimeBetweenRetriesIncreasingFactor( + float waitingTimeBetweenRetriesIncreasingFactor) + { + this.waitingTimeBetweenRetriesIncreasingFactor = waitingTimeBetweenRetriesIncreasingFactor; + } + +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryCallerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryCallerTest.java index f99a0b1d94f..d43f8a60856 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryCallerTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryCallerTest.java @@ -25,6 +25,8 @@ import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import ch.systemsx.cisd.common.retry.config.StaticRetryConfiguration; + /** * @author pkupczyk */ @@ -35,6 +37,8 @@ public class RetryCallerTest private Runnable runnable; + private StaticRetryConfiguration configuration; + private RetryCaller<Object, Throwable> caller; @BeforeMethod @@ -42,7 +46,13 @@ public class RetryCallerTest { mockery = new Mockery(); runnable = mockery.mock(Runnable.class); - caller = new RetryCaller<Object, Throwable>() + + configuration = new StaticRetryConfiguration(); + configuration.setMaximumNumberOfRetries(5); + configuration.setWaitingTimeBetweenRetries(100); + configuration.setWaitingTimeBetweenRetriesIncreasingFactor(2); + + caller = new RetryCaller<Object, Throwable>(configuration) { @Override protected Object call() throws Throwable @@ -51,9 +61,6 @@ public class RetryCallerTest return null; } }; - caller.setRetryWaitingTime(100); - caller.setRetryWaitingTimeFactor(2); - caller.setRetryMaxCounter(5); } @Test @@ -91,12 +98,11 @@ public class RetryCallerTest throws Throwable { final long startTime = System.currentTimeMillis(); - final long waitingTime = caller.getRetryWaitingTime(); mockery.checking(new Expectations() { { - for (int i = 0; i < caller.getRetryMaxCounter() - 1; i++) + for (int i = 0; i < configuration.getMaximumNumberOfRetries(); i++) { final int ifinal = i; oneOf(runnable).run(); @@ -105,7 +111,8 @@ public class RetryCallerTest public Object invoke(Invocation invocation) throws Throwable { Assert.assertTrue(System.currentTimeMillis() >= startTime - + (ifinal * waitingTime)); + + (ifinal * configuration + .getWaitingTimeBetweenRetries())); throw new RemoteConnectFailureException("", null); } }); @@ -125,7 +132,7 @@ public class RetryCallerTest mockery.checking(new Expectations() { { - for (int i = 0; i < caller.getRetryMaxCounter(); i++) + for (int i = 0; i < configuration.getMaximumNumberOfRetries() + 1; i++) { oneOf(runnable).run(); will(throwException(new RemoteConnectFailureException("", null))); diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryProxyFactoryTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryProxyFactoryTest.java index 1a365aecacc..5247211bb68 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryProxyFactoryTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/retry/RetryProxyFactoryTest.java @@ -20,14 +20,30 @@ import java.lang.reflect.InvocationTargetException; import org.springframework.remoting.RemoteConnectFailureException; import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import ch.systemsx.cisd.common.retry.config.DefaultRetryConfiguration; + /** * @author pkupczyk */ public class RetryProxyFactoryTest { + @BeforeMethod + public void beforeMethod() + { + DefaultRetryConfiguration.getInstance().setWaitingTimeBetweenRetries(100); + } + + @AfterMethod + public void afterMethod() + { + DefaultRetryConfiguration.getInstance().reset(); + } + @Test public void testCreateProxyForClassWithoutAnyInterfaceAndCallCommunicationFailingRetryMethod() throws Throwable -- GitLab