Spring Retry Basic Configuration with @Retriable
public class RetryTemplateConfiguration {
@SuppressWarnings("squid:S3749")
private final RetryTemplateConfigProperties config;
@SuppressWarnings("squid:S3749")
private final RetryLoggingListener retryLoggingListener;
@SuppressWarnings("squid:S3749")
private final RetryTemplateConfigProperties config;
@SuppressWarnings("squid:S3749")
private final RetryLoggingListener retryLoggingListener;
@Bean
public RetryTemplate retryTemplate() {
// FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
// fixedBackOffPolicy.setBackOffPeriod(2000l);
// retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
final Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
exceptionMap.put(RecoverableFailureException.class, true);
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(config.getTotalRetries(), exceptionMap));
retryTemplate.registerListener(retryLoggingListener);
final ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(config.getIntialInterval());
backOffPolicy.setMaxInterval(config.getMaxInterval());
backOffPolicy.setMultiplier(config.getMaxInterval());
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate;
}
public RetryTemplate retryTemplate() {
// FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
// fixedBackOffPolicy.setBackOffPeriod(2000l);
// retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
final Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
exceptionMap.put(RecoverableFailureException.class, true);
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(config.getTotalRetries(), exceptionMap));
retryTemplate.registerListener(retryLoggingListener);
final ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(config.getIntialInterval());
backOffPolicy.setMaxInterval(config.getMaxInterval());
backOffPolicy.setMultiplier(config.getMaxInterval());
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate;
}
@ConfigurationProperties(prefix = "abc.base.retry")
@Data
public class RetryTemplateConfigProperties {
private int intialInterval;
private int maxInterval;
private int multiplier;
private int totalRetries;
}
@Service
@Slf4j
public class RetryLoggingListener extends RetryListenerSupport {
@Override
public <T, E extends Throwable> void close(
RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
if (context.getRetryCount() > 0) {
log.info(
"%%% %%% %%% [{}] retry closing, count:{}",
context.getAttribute("context.name"), context.getRetryCount());
}
super.close(context, callback, throwable);
}
@Override
public <T, E extends Throwable> void onError(
RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
if (context.getRetryCount() > 0) {
log.info(
"%%% %%% %%% ["
+ context.getAttribute("context.name")
+ "] retry onError, count: {}"
+ context.getRetryCount()
+ ", exception type:"
+ throwable.getClass(),
throwable);
}
super.onError(context, callback, throwable);
}
@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
log.info("%%% %%% %%%, retry opening...");
return super.open(context, callback);
}
}
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@ActiveProfiles("retry")
class SpringRetryTest {
@Autowired private CallerService callerService;
@MockBean private RetriableService retriableService;
@BeforeAll
public static void setUp() {
System.setProperty("spring.profiles.active", "retry");
}
@Test
void retriesAfterOneFailAndThenPass() {
callerService.intialCall("name");
verify(retriableService, times(3)).retriableMethod("name");
}
@Configuration
@EnableRetry
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Profile("retry")
public static class Application {
private final RetriableService retriableService;
public Application(RetriableService bService) {
this.retriableService = bService;
}
@SuppressWarnings("unchecked")
@Bean
public CallerService aService() {
when(retriableService.retriableMethod("name")).thenThrow(RecoverableFailureException.class).thenThrow(RecoverableFailureException.class).thenReturn("full name");
return Mockito.spy(new CallerServiceImpl(retriableService));
}
@Bean
public RetryLoggingListener retryLoggingListener() {
return new RetryLoggingListener();
}
}
}
public interface CallerService {
String intialCall(String name);
}
@Service
public class CallerServiceImpl implements CallerService {
private final RetriableService retriableService;
public CallerServiceImpl(RetriableService retriableService) {
this.retriableService = retriableService;
}
@Override
@Retryable(
value = {RecoverableFailureException.class},
maxAttempts = 6,
backoff = @Backoff(delay = 1000, multiplier = 2, maxDelay = 1800000),
listeners = {"retryLoggingListener"})
public String intialCall(String name) {
return this.retriableService.retriableMethod(name);
}
}
public interface RetriableService {
String retriableMethod(String name);
}
No comments:
Post a Comment