Оформлена ли функция возврата Retry threadsafe? - PullRequest
1 голос
/ 17 мая 2019

У меня есть класс, который отправляет сообщение удаленной службе, как показано ниже.Я использую resilience4j-retry, чтобы повторить сетевой вызов.Поскольку экземпляр retry является потокобезопасным в соответствии с документацией, я создаю его на уровне класса и повторно использую его.

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;
    }

}

Мой вопрос, является ли декорированная функция, возвращаемая Retry.decorateFunction(retry, this::postMessage);, также потокобезопасной?

В этом случае я мог бы переместить это на уровень класса вместо того, чтобы повторять это каждый раз, когда вызывается функция postMessageWithRetry.

1 Ответ

0 голосов
/ 24 мая 2019

Изучив код resilience4j-retry, я обнаружил, что декорированная функция фактически безопасна для потоков; до тех пор, пока функция, которую мы украшаем, в первую очередь является поточно-ориентированной.

Так что я могу переписать код, как показано ниже, так как функция postMessage является поточно-ориентированной, и поэтому декорированная функция postMessageFunction также является поточно-ориентированной.

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;
    }

}    
...