vsilaev/tascalate-concurrent

How to wrap a Promise into Promise.retry

Closed this issue · 5 comments

I am using the jersey rx() extension that wraps the requests in CompletionStages. I would like to be able to take this CompletionStage, convert it to a Promise, and use it within a Promises.retry without having to call get().

This means that Promises.retry would accept a Promise, rather than a Callable or Runnable, and then be able to resubmit the original code with binding context for re-execution.

Here is a retry function that I wrote to handle retries that has been adapted to work with Promises.

protected Promise<T> retry(Callable<CompletionStage<T>> callable) throws Exception {
        
        int retries = 0;
        boolean isRetry = false;
        
        do {
            try {
                if (isRetry) {
                    logger.warn(String.format("Retrying previous request (%s).", retries));
                }
                
                return Promises.from(callable.call());
            } catch (final Exception e) {
                logger.error("An exception was thrown while processing request.", e);
    
                isRetry = true;
                if (retries >= maxRetries) {
                    throw e;
                }
            }
            
            //
            // Back off for two seconds to try and not saturate the server with retry attempts.
            //
            Thread.sleep(2000);
        } while (retries++ < maxRetries);
        
        throw new RuntimeException("The number of maximum retries has been exceeded for this request.");
    }

Jeffrey,

If I understand your requirements correctly, then:

  1. You have Callable<CompletionStage<T>> callable that returns a new CompletionStage whenever it's called.
  2. You should use net.tascalate.concurrent.Promises.retryFuture(callable, retryPolicy)
  3. In your case retryPolicy is:
RetryPolicy<T> retryPolicy = new RetryPolicy<>(maxRetries, DelayPolicy.fixedInterval(2000L));

Is it what you need?

It looks right. I don't know how I didn't see the retryFuture method before...

How are exceptions handled?

Jeffrey,

Unfortunately, RetryPolicy class is not documented yet, but you can specify what exceptions are re-tryable and what should stop processing. Please check sources of the class -- but, in general, everything is configurable.

And, btw, in my example above you should use:

RetryPolicy<T> retryPolicy = new RetryPolicy<>(
  maxRetries, 
  DelayPolicy.fixedInterval(2000L).withFirstRetryNoDelay() 
);

To avoid waiting before the first execution

This worked. I apologize for not providing a follow up!