Подтвердить что ты не робот

Дизайн шаблона для "повторной" логики, которая не удалась?

Я пишу некоторую логику повторного подключения, чтобы периодически пытаться установить соединение с удаленной конечной точкой, которая опустилась. По сути, код выглядит следующим образом:

public void establishConnection() {
    try {
        this.connection = newConnection();
    } catch (IOException e) {
        // connection failed, try again.
        try { Thread.sleep(1000); } catch (InterruptedException e) {};

        establishConnection();
    }
}

Я решил эту общую проблему с кодом, подобным вышеизложенному, во многих случаях, но я чувствую себя в значительной степени неудовлетворенным результатом. Существует ли шаблон проектирования, предназначенный для решения этой проблемы?

4b9b3361

Ответ 1

Выйти из одной библиотеки стоит Sarge, которая автоматически выполняет повторы в соответствии с определенным планом.

Ответ 2

Бесстыдный плагин: я реализовал некоторые классы, чтобы разрешить повторные операции. Библиотека еще не доступна, но вы можете развить ее на github.. И существует вилка.

Он позволяет создавать Retryer с различными гибкими стратегиями. Например:

Retryer retryer = 
    RetryerBuilder.newBuilder()
                  .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECOND))
                  .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                  .retryIfExceptionOfType(IOException.class)
                  .build();

И затем вы можете выполнить вызываемый (или несколько) с помощью Retryer:

retryer.call(new Callable<Void>() {
    public Void call() throws IOException {
        connection = newConnection();
        return null;
    }
}

Ответ 4

Я использую аннотации AOP и Java. Существует готовый механизм в jcabi-аспекты (я разработчик):

@RetryOnFailure(attempts = 3, delay = 1, unit = TimeUnit.SECONDS)
public void establishConnection() {
  this.connection = newConnection();
}

пс. Вы также можете попробовать RetryScalar из Cactoos.

Ответ 5

Используя Failsafe (автор здесь):

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(IOException.class)
  .withMaxRetries(5)
  .withDelay(1, TimeUnit.SECONDS);

Failsafe.with(retryPolicy).run(() -> newConnection());

Никаких аннотаций, без магии, не обязательно быть приложением Spring и т.д. Просто и просто.

Ответ 6

нет ничего особенного в повторной попытке - возьмите этот класс в качестве примера http://www.docjar.com/html/api/org/springframework/jms/listener/DefaultMessageListenerContainer.java.html Как вы можете видеть даже spring разработчики все еще пишут код для повторной попытки - строка 791... нет такой особой картины AFAIK..

Что я могу посоветовать для работы с ресурсами, это взять библиотеку пула apache commons - проверьте http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html и посетите http://commons.apache.org/pool

Ответ 7

Вы можете попробовать spring-retry, он имеет чистый интерфейс и прост в использовании.

Пример:

 @Retryable(maxAttempts = 4, backoff = @Backoff(delay = 500))
 public void establishConnection() {
    this.connection = newConnection();
 } 

В случае исключения он будет повторять (вызывать) до 4 раз метод установить соединение() с политикой отсрочки 500 мс

Ответ 8

Это может быть что-то вроде этого:

try {
  // logic
} re-try {
  // retry logic
} re-re-try {
  // reretry logic
} catch(Exception ex) {
  // log
}