in safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BaseRetryInterceptor.java [56:101]
public Object retry(final InvocationContext context) throws Exception {
final Map<Key, Model> models = cache.getModels();
final Key cacheKey = new Key(context, cache.getUnwrapped());
Model model = models.get(cacheKey);
if (model == null) {
model = cache.create(context);
final Model existing = models.putIfAbsent(cacheKey, model);
if (existing != null) {
model = existing;
}
}
if (model.disabled) {
return context.proceed();
}
final Map<String, Object> contextData = context.getContextData();
final Object id = contextData.get(IdGeneratorInterceptor.class.getName());
final String contextKey = BaseRetryInterceptor.class.getName() + ".context_" + id;
Context retryContext = Context.class.cast(contextData.get(contextKey));
if (retryContext == null) {
retryContext = new Context(System.nanoTime() + model.maxDuration, model.maxRetries);
contextData.put(contextKey, retryContext);
}
while (retryContext.counter >= 0) { // todo: handle async if result is a Future or CompletionStage (weird no?)
try {
final Object proceed = context.proceed();
if (retryContext.counter == model.maxRetries) {
executeFinalCounterAction(contextData, model.callsSucceededNotRetried);
} else {
executeFinalCounterAction(contextData, model.callsSucceededRetried);
}
if (BaseAsynchronousInterceptor.BaseFuture.class.isInstance(proceed)) {
final Model modelRef = model;
contextData.put(BaseAsynchronousInterceptor.BaseFuture.class.getName() + ".errorHandler_" + id,
(BaseAsynchronousInterceptor.ErrorHandler<Exception, Future<?>>) error -> {
handleException(contextData, contextKey, modelRef, error);
return Future.class.cast(context.proceed());
});
}
return proceed;
} catch (final Exception re) {
retryContext = handleException(contextData, contextKey, model, re);
}
}
throw new FaultToleranceException("Inaccessible normally, here for compilation");
}