This repository has been archived by the owner on Jun 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Alternate RetryConfigBuilder to group relevant configs together for u…
…ser of use contains few groups AlternateRetryConfigBuilder is the alternate implementation Usage is described using AlternateRetryConfigBuilder Many subclasses are designed mutable for use like Builders Many subclasses could be extracted to become parent level classes in their own files
- Loading branch information
raghavan chockalingam
committed
Sep 6, 2018
1 parent
d0635b3
commit 158dbbd
Showing
2 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
184 changes: 184 additions & 0 deletions
184
src/main/java/com/evanlennick/retry4j/config/AlternateRetryConfigBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package com.evanlennick.retry4j.config; | ||
|
||
import com.evanlennick.retry4j.backoff.*; | ||
import com.evanlennick.retry4j.exception.InvalidRetryConfigException; | ||
|
||
import java.time.Duration; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
|
||
public class AlternateRetryConfigBuilder { | ||
|
||
private Object valueToRetryOn; | ||
private Boolean retryOnValue = false; | ||
// Using some defaults here, but we need not declare defaults and validate for nulls during `build()` | ||
private BackoffStrategy backoffStrategy = BackoffStrategyFactory.withFixedBackoff(); | ||
private ExceptionRetryConfig exceptionRetryConfig = new ExceptionRetryConfig() | ||
.retryOnAnyException(); | ||
private TimingRetryConfig timingRetryConfig = TimingRetryConfig.retryIndefinitely() | ||
.withDelayBetweenTries(2, ChronoUnit.SECONDS); | ||
|
||
private AlternateRetryConfigBuilder() { | ||
} | ||
|
||
public static AlternateRetryConfigBuilder exceptionRetryConfig(ExceptionRetryConfig exceptionRetryConfig) { | ||
AlternateRetryConfigBuilder builder = new AlternateRetryConfigBuilder(); | ||
builder.exceptionRetryConfig = exceptionRetryConfig; | ||
return builder; | ||
} | ||
|
||
public static AlternateRetryConfigBuilder retryOnReturnValue(Object value) { | ||
AlternateRetryConfigBuilder builder = new AlternateRetryConfigBuilder(); | ||
builder.valueToRetryOn = value; | ||
builder.retryOnValue = true; | ||
return builder; | ||
} | ||
|
||
public static class ExceptionRetryConfig { | ||
private Boolean retryOnAnyException = false; | ||
private Function<Exception, Boolean> customRetryOnLogic; | ||
private ExceptionsCriteria exceptionsCriteriaBuilder = new ExceptionsCriteria(); | ||
|
||
public static ExceptionRetryConfig retryOnAnyException() { | ||
ExceptionRetryConfig config = new ExceptionRetryConfig(); | ||
config.retryOnAnyException = true; | ||
return config; | ||
} | ||
|
||
public static ExceptionRetryConfig failOnAnyException() { | ||
ExceptionRetryConfig config = new ExceptionRetryConfig(); | ||
config.retryOnAnyException = false; | ||
return config; | ||
} | ||
|
||
public static ExceptionRetryConfig retryOnExceptions(ExceptionsCriteria exceptionsCriteriaBuilder) { | ||
ExceptionRetryConfig config = new ExceptionRetryConfig(); | ||
config.exceptionsCriteriaBuilder = exceptionsCriteriaBuilder; | ||
return config; | ||
} | ||
|
||
public static ExceptionRetryConfig retryOnCustomExceptionLogic(Function<Exception, Boolean> customRetryFunction) { | ||
ExceptionRetryConfig config = new ExceptionRetryConfig(); | ||
config.customRetryOnLogic = customRetryFunction; | ||
return config; | ||
} | ||
} | ||
|
||
public static class ExceptionsCriteria { | ||
private Set<Class<? extends Exception>> retryOnSpecificExceptions = new HashSet<>(); | ||
private Set<Class<? extends Exception>> retryOnAnyExceptionExcluding = new HashSet<>(); | ||
private boolean retryOnCausedBy; | ||
|
||
public ExceptionsCriteria retryOnSpecificExceptions(Class<? extends Exception>... exceptions) { | ||
this.retryOnSpecificExceptions = new HashSet<>(Arrays.asList(exceptions)); | ||
return this; | ||
} | ||
|
||
public ExceptionsCriteria retryOnAnyExceptionExcluding(Class<? extends Exception>... exceptions) { | ||
this.retryOnAnyExceptionExcluding = new HashSet<>(Arrays.asList(exceptions)); | ||
return this; | ||
} | ||
|
||
public ExceptionsCriteria retryOnCausedBy() { | ||
this.retryOnCausedBy = true; | ||
return this; | ||
} | ||
} | ||
|
||
public static class TimingRetryConfig { | ||
|
||
private Integer maxNumberOfTries; | ||
private Duration delayBetweenRetries; | ||
public static final String SHOULD_SPECIFY_DELAY_BETWEEN_RETRIES_AS_POSTIVE__ERROR_MSG | ||
= "Delay between retries must be a non-negative Duration."; | ||
|
||
private TimingRetryConfig() { | ||
} | ||
|
||
public static TimingRetryConfig withMaxTries(int maxTries) { | ||
TimingRetryConfig config = new TimingRetryConfig(); | ||
config.maxNumberOfTries = maxTries; | ||
return config; | ||
} | ||
|
||
public static TimingRetryConfig retryIndefinitely() { | ||
TimingRetryConfig config = new TimingRetryConfig(); | ||
config.maxNumberOfTries = Integer.MAX_VALUE; | ||
return config; | ||
} | ||
|
||
|
||
public TimingRetryConfig withDelayBetweenTries(Duration duration) { | ||
if (duration.isNegative()) { | ||
throw new InvalidRetryConfigException(SHOULD_SPECIFY_DELAY_BETWEEN_RETRIES_AS_POSTIVE__ERROR_MSG); | ||
} | ||
|
||
delayBetweenRetries = duration; | ||
return this; | ||
} | ||
|
||
public TimingRetryConfig withDelayBetweenTries(long amount, ChronoUnit time) { | ||
delayBetweenRetries = Duration.of(amount, time); | ||
return this; | ||
} | ||
|
||
} | ||
|
||
public static class BackoffStrategyFactory { | ||
|
||
public static BackoffStrategy withFixedBackoff() { | ||
return new FixedBackoffStrategy(); | ||
} | ||
|
||
public static BackoffStrategy withExponentialBackoff() { | ||
return new ExponentialBackoffStrategy(); | ||
} | ||
|
||
public static BackoffStrategy withFibonacciBackoff() { | ||
return new FibonacciBackoffStrategy(); | ||
} | ||
|
||
public static BackoffStrategy withNoWaitBackoff() { | ||
return new NoWaitBackoffStrategy(); | ||
} | ||
|
||
public static BackoffStrategy withRandomBackoff() { | ||
return new RandomBackoffStrategy(); | ||
} | ||
|
||
public static BackoffStrategy withRandomExponentialBackoff() { | ||
return new RandomExponentialBackoffStrategy(); | ||
} | ||
|
||
} | ||
|
||
public AlternateRetryConfigBuilder withBackoffStrategy(BackoffStrategy backoffStrategy) { | ||
this.backoffStrategy = backoffStrategy; | ||
return this; | ||
} | ||
|
||
public AlternateRetryConfigBuilder withExceptionRetryconfig(ExceptionRetryConfig exceptionRetryConfig) { | ||
this.exceptionRetryConfig = exceptionRetryConfig; | ||
return this; | ||
} | ||
|
||
public AlternateRetryConfigBuilder withTimingRetryConfig(TimingRetryConfig timingRetryConfig) { | ||
this.timingRetryConfig = timingRetryConfig; | ||
return this; | ||
} | ||
|
||
public RetryConfig build() { | ||
RetryConfig retryConfig = new RetryConfig( | ||
exceptionRetryConfig.retryOnAnyException, exceptionRetryConfig.exceptionsCriteriaBuilder.retryOnSpecificExceptions, | ||
exceptionRetryConfig.exceptionsCriteriaBuilder.retryOnAnyExceptionExcluding, timingRetryConfig.maxNumberOfTries, | ||
timingRetryConfig.delayBetweenRetries, backoffStrategy, valueToRetryOn, retryOnValue, | ||
exceptionRetryConfig.customRetryOnLogic, exceptionRetryConfig.exceptionsCriteriaBuilder.retryOnCausedBy | ||
); | ||
return retryConfig; | ||
} | ||
|
||
} | ||
|
71 changes: 71 additions & 0 deletions
71
src/test/java/com/evanlennick/retry4j/AlternateRetryConfigBuilderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package com.evanlennick.retry4j; | ||
|
||
|
||
import com.evanlennick.retry4j.config.AlternateRetryConfigBuilder; | ||
import com.evanlennick.retry4j.config.AlternateRetryConfigBuilder.BackoffStrategyFactory; | ||
import com.evanlennick.retry4j.config.AlternateRetryConfigBuilder.ExceptionRetryConfig; | ||
import com.evanlennick.retry4j.config.AlternateRetryConfigBuilder.ExceptionsCriteria; | ||
import com.evanlennick.retry4j.config.AlternateRetryConfigBuilder.TimingRetryConfig; | ||
import org.testng.annotations.Test; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.time.temporal.ChronoUnit; | ||
|
||
public class AlternateRetryConfigBuilderTest { | ||
|
||
@Test | ||
public void testConfig1() { | ||
AlternateRetryConfigBuilder | ||
.exceptionRetryConfig( | ||
new ExceptionRetryConfig().retryOnAnyException() | ||
) | ||
.withTimingRetryConfig( | ||
TimingRetryConfig.withMaxTries(200) | ||
) | ||
.withBackoffStrategy(BackoffStrategyFactory.withNoWaitBackoff()) | ||
.build(); | ||
} | ||
|
||
@Test | ||
public void testConfig2() { | ||
AlternateRetryConfigBuilder | ||
.exceptionRetryConfig( | ||
new ExceptionRetryConfig().retryOnExceptions(new ExceptionsCriteria() | ||
.retryOnSpecificExceptions(IllegalArgumentException.class)) | ||
) | ||
.withTimingRetryConfig( | ||
TimingRetryConfig.retryIndefinitely().withDelayBetweenTries(3, ChronoUnit.MINUTES) | ||
) | ||
.withBackoffStrategy(BackoffStrategyFactory.withExponentialBackoff()) | ||
.build(); | ||
} | ||
|
||
@Test | ||
public void testConfig3() { | ||
AlternateRetryConfigBuilder | ||
.exceptionRetryConfig( | ||
new ExceptionRetryConfig().retryOnExceptions(new ExceptionsCriteria() | ||
.retryOnSpecificExceptions(IOException.class) | ||
.retryOnAnyExceptionExcluding(FileNotFoundException.class) | ||
.retryOnCausedBy()) | ||
) | ||
.withTimingRetryConfig( | ||
TimingRetryConfig.retryIndefinitely().withDelayBetweenTries(3, ChronoUnit.MINUTES) | ||
) | ||
.withBackoffStrategy(BackoffStrategyFactory.withExponentialBackoff()) | ||
.build(); | ||
} | ||
|
||
@Test | ||
public void testConfig4() { | ||
AlternateRetryConfigBuilder | ||
.retryOnReturnValue("retry on this value!") | ||
.withTimingRetryConfig( | ||
TimingRetryConfig.retryIndefinitely() | ||
) | ||
.withBackoffStrategy(BackoffStrategyFactory.withFibonacciBackoff()) | ||
.build(); | ||
} | ||
|
||
} |