Skip to content
Snippets Groups Projects
Commit a6aa75bb authored by pkupczyk's avatar pkupczyk
Browse files

LMS-2675 - InfectX: retry API methods when they fail - make it configurable

SVN: 23892
parent fe6b0e19
No related branches found
No related tags found
No related merge requests found
......@@ -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;
}
}
/*
* 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;
}
}
/*
* 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();
}
/*
* 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;
}
}
......@@ -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)));
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment