Таймер Akka FSM прекращает отправку сообщения

У меня есть актер Akka FSM, который использует SetTimer на неопределенный срок. Несколько раз я видел, что таймер не отправляет сообщение. Кто-нибудь видел такое поведение или какие-либо ошибки, которых мне следует избегать при использовании FSM?

Вот некоторая информация о том, как работает мой код.

У меня есть Akka FSM, который ожидает поступления файлов. по приезду разбираю их и храню в памяти. У меня есть таймер, который вызывается каждый час и отправляет себе сообщение PushTODB. Когда FSM получает это сообщение, он переходит в состояние неполучения и начинает работать с pushTODB. когда pushTODB завершается успешно, я получаю сообщение от актера DAL (который работает с базой данных), и FSM возвращается в состояние приема. Так что все упирается в то, что я получаю периодические сообщения PushTODB.

Любая помощь или идея приветствуются. Спасибо Манас

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

  class FileMonitor extends Actor with ActorLogging
     with LoggingFSM[Status, Data]{
   val config = context.system.settings.config
   val landingZones = ConfigUtils.getLZInfoList(config)
   val pushToDBFreq =  1 hour
   val manager = context.actorOf(Props(new MMSIManager))
   manager ! Activate
   var collection = ActorRef.noSender
   val workingFolder = "/tmp"
   val UOWProvCH1 = "ch1path"
   val UOWProvCH2 = "ch2path"

  startWith(Idle, toBeHandled(Seq(newFile(Paths.get("")))))
  when(Idle, inf) {
    case Event(Activate(ref, again), list) =>
      collection = ref
      init(again)
      goto(Active) using list
  }
 when(Active, inf) {
    case Event(nf @ newFile(someFile, au, nextau), list: toBeHandled) =>
    dosomething()
    stay

   case Event(BeIdle, list: toBeHandled) =>
     log.info("Asking manager to pushToDB........")
     manager ! pushToDB()
     goto(NonTransmitting) using list
 }
 when(NonTransmitting, inf) {
   case Event(event :pushToDBSuccess, list: toBeHandled) =>
     log.debug("received pushTODBSucess message...............")
     cleanit(list)
     list.fileName.foreach(file => sendPositional(file))
     goto(Active) using list.copy(fileName = Seq.empty)
 }
 whenUnhandled{
   case Event(nf :newFile, list @ toBeHandled(l)) =>
     list.copy(fileName = l :+nf )
     stay using list
  stay
   case x => log.warning(s"Got message $x.........")
     stay
 }
 onTransition {
    case Idle -> Active => {
      setTimer("BeIdle", BeIdle, 1 hour, true)
      log.info("Going Active............")
 }
}

В качестве обходного пути я проверяю, активен ли таймер, и воссоздаю его; но я хотел бы знать, есть ли что-то, что я делаю здесь неправильно или что-то упускаю, из-за чего таймер не отправляет сообщение BeIdle. Иногда он работает несколько часов, а затем BeIdle перестает появляться, а по крайней мере в одном экземпляре BeIdle вообще не появлялся.

Надеюсь, этот код поможет понять проблему.

..Манас


person Manas    schedule 01.10.2014    source источник
comment
Можете ли вы опубликовать свой код?   -  person Ryan    schedule 01.10.2014


Ответы (1)


Одна подозрительная вещь заключается в том, что вы запускаете новый таймер при каждом переходе от простоя к активному.

Рассмотрите возможность вызова cancelTimer("BeIdle") при выходе из активного статуса или запустите один таймер в блоке preStart.

person Dragisa Krsmanovic    schedule 07.10.2014
comment
Мой актер всегда начинает Idle. Родитель отправляет сообщение активации. Родитель также является супервизором этого актера, поэтому в случае сбоя моего актера супервизор перезапустит его. В настоящее время я проверяю, жив ли таймер, а если нет; Я создаю новый таймер. Я немного не понимаю, что произойдет, если мой актер выйдет из строя; таймер тоже вылетит или останется? .. Манас - person Manas; 13.10.2014