Thomas
Thomas

Reputation: 4330

Is decorated function returned by Retry threadsafe?

I have a class that sends a message to a remote service as shown below. I'm using resilience4j-retry to retry the network call. As the retry instance is thread safe according to the documentation, I'm creating it in the class level and reusing it.

public class RemoteMessageService {

    Retry retry = Retry.of("RemoteMessageService", RetryConfig.custom()
        .maxAttempts(5)
        .retryExceptions(ProcessingException.class)
        .intervalFunction(IntervalFunction.ofExponentialBackoff())
        .build());    

    public void postMessageWithRetry(final String message){

        Function<Integer, Void> postMessageFunction = Retry.decorateFunction(retry, this::postMessage);

        try {
            postMessageFunction.apply(message)
        } catch (final ProcessingException e) {
            LOG.warn("Got processing exception: {}", e.getMessage());
        } catch (final Exception e) {
            LOG.error("Got unknown exception: {}", e.getMessage());
        }
    }

    private Void postMessage(final String message){
        // Do a network call to send the message to a rest service
        // throw ProcessingException in case of timeout
        return null;
    }

}

My question is if the decorated function returned by Retry.decorateFunction(retry, this::postMessage); is also thread safe?

In that case I could move this to class level instead of repeating it every time the postMessageWithRetry function is called.

Upvotes: 2

Views: 1099

Answers (1)

Thomas
Thomas

Reputation: 4330

After looking into the resilience4j-retry code, I found that the decorated function is in fact thread safe; as long as the function that we decorate in the first place is thread safe.

So I can rewrite the code as below since the postMessage function is thread safe, and therefor the decorated postMessageFunction function is also thread safe.

public class RemoteMessageService {

    private final Retry retry = Retry.of("RemoteMessageService", RetryConfig.custom()
        .maxAttempts(5)
        .retryExceptions(ProcessingException.class)
        .intervalFunction(IntervalFunction.ofExponentialBackoff())
        .build());    

    private final Function<Integer, Void> postMessageFunction = Retry.decorateFunction(retry, this::postMessage);

    public void postMessageWithRetry(final String message) {

        try {
            postMessageFunction.apply(message)
        } catch (final ProcessingException e) {
            LOG.warn("Got processing exception: {}", e.getMessage());
        } catch (final Exception e) {
            LOG.error("Got unknown exception: {}", e.getMessage());
        }
    }

    private Void postMessage(final String message) {
        // Do a network call to send the message to a rest service
        // throw ProcessingException in case of timeout
        return null;
    }

}    

Upvotes: 2

Related Questions