Повторная попытка актера с отсрочкой и лимитом повторных попыток

Мне нужен механизм повторных попыток для актеров akka с увеличением времени между повторными попытками и максимальным лимитом повторных попыток. Для этой цели я пытаюсь использовать шаблон BackOffSupervisor, предоставленный akka. Проблема в том, что, судя по моему тесту, стратегия отсрочки и лимит повторных попыток не работают. А может проблема в тесте?

Тест выглядит так:

Простой актор, который выдает исключение при первых 5 сообщениях.

class SomeActor extends AbstractActor {

private static int messageCounter = 0;

//return the message to sender
@Override
public void preRestart(final Throwable reason, final Optional<Object> message) {
    getSelf().tell(message.get(), getSender());
}


@Override
public Receive createReceive() {
    return receiveBuilder()
            .matchEquals("hello", message -> {
                messageCounter++;
                getSender().tell("response", getSelf());

                //Throw Exception at the first 5 messages
                if (messageCounter < 5) {
                    throw new Exception();
                }

            })
            .build();
}

}

Конфигурация BackOffSupervisor

private ActorRef createSupervisedActor(Class<? extends Actor> actorClass) {
    final Props someActorProps = Props.create(actorClass);

    final Props supervisorProps = BackoffSupervisor.props(
            Backoff.onStop(
                    someActorProps, //actor to be supervised
                    "someActor",
                    Duration.ofSeconds(10), //min back-off time
                    Duration.ofMinutes(2), // max back-off time
                    0.2, // back-off increase factor
                    10) // max retry limit
                    .withSupervisorStrategy(
                            new OneForOneStrategy(
                                    DeciderBuilder
                                            .match(Exception.class, e -> SupervisorStrategy.restart())
                                            .matchAny(o -> SupervisorStrategy.escalate())
                                            .build())
                    )
    );

    return testSystem.actorOf(supervisorProps);

}

И метод проверки

    @Test
public void test() {
    new TestKit(testSystem) {{
        ActorRef actorRef = createSupervisedActor(SomeActor.class);

        actorRef.tell("hello", getRef());

        //Expect 5 responses in 1 second
        receiveN(5, Duration.ofSeconds(1));
    }};

}

Тест заканчивается слишком быстро. Менее чем за секунду, если исходить из конфигурации BackoffSupervisor, я ожидаю, что это займет не менее 50 секунд.


person Borislav Nikolov    schedule 18.10.2018    source источник


Ответы (1)


Проблема возникла по следующей причине:

Вызов исключения в дочернем актере (в моем случае someActor) не обрабатывается Backoff.onStop и, следовательно, обрабатывается обычным контролем по умолчанию, что означает немедленный перезапуск. - https://github.com/akka/akka/issues/23406#issuecomment-372602568

person Borislav Nikolov    schedule 19.10.2018