code: @SuppressWarnings("unchecked")
    public static <T> ComposableFuture<T> retry(final int retries, final Function<Integer, ComposableFuture<T>> producer) {
      final BiFunction<BiFunction, Integer, ComposableFuture<T>> retriable = (f, attempt) ->
        Try.apply(() -> producer.apply(attempt)).
          recover(ComposableFutures::fromError).
          map(action -> action.recoverWith(error -> {
              if (attempt >= retries) {
                return fromError(error);
              }
  
              // we can't safely use generics here since we'll get into infinite nested generics
              return (ComposableFuture<T>) f.apply(f, attempt + 1);
            })
          ).getValue();
  
      return retriable.apply(retriable, 0);
    }
docs: retries a given operation N times for each computed Failed future.
  
  @param retries  attempts amount
  @param producer future producer
  @param <T>      result value type
  @return future containing retry result value