class RetryableExecutor implements Executor<T> {

    @Override
    public T execute()
    {
        logger.debug("Initializing retry");
        RetryPolicy<Object> policy = new RetryPolicy<>();

        if (retryableExceptions != null && retryableExceptions.size() > 0)
        {
            policy.handle(retryableExceptions);
        }

        if (nonRetryableExceptions != null && nonRetryableExceptions.size() > 0)
        {
            policy.abortOn(nonRetryableExceptions);
        }

        policy = policy.withMaxRetries(maxRetries);

        return Failsafe
            .with(policy)
            .onFailure(executionCompletedEvent ->
            {
                currentRetry++;
                logger.error("Retrying Operation {} :", currentRetry, executionCompletedEvent.getFailure());
            })
            .get((() ->
            {
                logger.debug("Running Operation - Attempt: {}", currentRetry);
                return executor.execute();
            }));
    }

    public  RetryableExecutor(
        Executor<T> executor,
        int maxRetries);
    public  RetryableExecutor(
        Executor<T> executor,
        int maxRetries,
        List<Class<? extends Throwable>> retryableExceptions);
    public  RetryableExecutor(
        Executor<T> operationPerformer,
        int maxRetries,
        List<Class<? extends Throwable>> retryableExceptions,
        List<Class<? extends Throwable>> nonRetryableExceptions);

}