rhuffman / re-retrying

A Java library to allow for the creation of configurable retrying strategies for an arbitrary function call, such as something that communicates with a remote service with flaky uptime.
Apache License 2.0
35 stars 6 forks source link

retryIfCondition(BooleanSupplier condition) #31

Closed Bennett-Lynch closed 6 years ago

Bennett-Lynch commented 6 years ago

Scenario: I'm dealing with a somewhat poorly designed Http client. I want to retry on failed request attempts. However, the client's sendRequest method returns void, and does not throw exceptions on failures. Instead, I have to manually query the client.getStatusCode().

I want to retry if client.getStatusCode() is 500 or 503, for example. To do this today, I need to wrap my execution logic in some method that will send the request, followed by a separate statement to get/return the status code. Ideally, I'd like to be able to do just this:

Client client = new Client();

Retryer<Object> retryer = RetryerBuilder.newBuilder()
    .retryIfCondition(() -> client.getStatusCode() == 500 || client.getStatusCode() == 503)
    // with some wait & stop strategy
    .build();

I've encountered other scenarios where a retryIfCondition(BooleanSupplier condition) would be useful as well. Essentially whenever you want to retry based on the state change of some object, but not necessarily the return value of a given method.

rhuffman commented 6 years ago

I don't really see how your suggestion could work. The Retryer is designed to run some bit of code (the Callable you pass to Retry), test the result against, and retry the Callable if the result is not satisfactory.

In your case, you need to retry sending a request if the status code is 500 or 503. So you need a Callable that sends the request, and returns the status code.

So unless I misunderstand what saying, you need to do is something like this:

        Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
                .retryIfResult(status -> status == 500 || status == 503)
                .build();
        retryer.call(() -> {
            client.sendRequest(request);
            return client.getStatusCode();
        });

I'm going to close this, but if you feel like I'm missing something about what you're trying to do let me know.