Akka FSM计时器停止发送消息

时间:2014-10-01 15:52:15

标签: scala akka fsm

我有一个无限期使用SetTimer的Akka FSM actor。我已经看过很多次计时器不会发送消息。有没有人看到过这种行为或使用FSM时我必须避免的任何问题?

以下是有关我的代码如何工作的一些信息。

我有一个等待文件到达的Akka FSM。到达后,我会解析它们并将它们存储在我的记忆中。我有一个每小时调用一次的计时器,并向自己发送一个PushTODB消息。当FSM收到该消息时,它进入非接收状态并且推送TODB工作。当pushTODB成功时,我收到来自DAL actor的消息(它使数据库工作)并且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根本没有出现。

希望此代码有助于理解问题。

..马纳斯

1 个答案:

答案 0 :(得分:0)

一个可疑的事情是,您正在从空闲到活动的每次转换中开始新的计时器。

在退出活动状态时调用cancelTimer("BeIdle")或在preStart块中启动单个计时器。