public Object retry()

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");
    }