简体   繁体   English

Akka FSM计时器停止发送消息

[英]Akka FSM timer stops sending message

I have a Akka FSM actor that uses a SetTimer indefinitely. 我有一个Akka FSM演员,它无限期地使用SetTimer。 I have seen it few times that the timer does not dispatch the message. 我已经看到几次定时器不调度消息。 Has anyone seen this behavior or any gotcha that I have to avoid while using FSM? 有没有人看到过这种行为或使用FSM时必须避免的任何陷阱?

Here is some information about how my code works. 这里是有关我的代码如何工作的一些信息。

I have a Akka FSM that waits for files to arrive. 我有一个等待文件到达的Akka FSM。 upon arrival I parse them and store them in my memory. 到达后,我解析它们并将它们存储在我的记忆中。 I have a timer that gets called every hour and sends a PushTODB message to self. 我有一个计时器,它每个小时都会被调用,并向自己发送一个PushTODB消息。 When FSM receives that message it goes to a non-receiving state and does pushTODB work. 当FSM接收到该消息时,它将进入非接收状态,并且pushTODB会工作。 when pushTODB is successful I receive a message from the DAL actor(which does the database work) and the FSM goes back to receiving state. 当pushTODB成功时,我从DAL actor(该数据库起作用)接收到一条消息,而FSM返回到接收状态。 So everything hangs on the fact that I receive periodic PushTODB message. 因此,一切都取决于我收到定期的PushTODB消息的事实。

Any help or idea is welcome. 欢迎任何帮助或想法。 Thanks Manas 谢谢玛纳斯

Adding the code to help understand the question. 添加代码以帮助理解问题。 The code is bit modified to hide some details that are not important for this discussion but after stubbing the non-important function this is what the code looks like 对代码进行了一些修改,以隐藏一些对于本次讨论不重要的细节,但是在对不重要的函数进行存根之后,代码看起来像

  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............")
 }
}

As a work around I am checking if the timer is active and re-creating it; 作为解决方法,我正在检查计时器是否处于活动状态并重新创建它。 but I would love to know if there is something that I am doing wrong here or missing anything because of which the timer does not dispatch BeIdle message. 但是我很想知道我是否在做错这里或错过什么,因为计时器没有调度BeIdle消息。 Sometime it works for few hours and then BeIdle stops showing up and at least on one instance BeIdle did not show up at all. 有时它会工作几个小时,然后BeIdle停止显示,并且至少在一个实例上BeIdle根本没有显示。

Hope this code help to understand the problem. 希望此代码有助于理解问题。

..Manas ..法力

One fishy thing is that you are starting a new timer on every transition from Idle to Active. 一件令人毛骨悚然的事情是,您在从空闲到活动的每个过渡中都启动了一个新计时器。

Consider calling cancelTimer("BeIdle") when exiting Active status or start a single timer in preStart block. 当退出活动状态或在preStart块中启动单个计时器时,请考虑调用cancelTimer("BeIdle")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM