I have a Akka FSM actor that uses a SetTimer indefinitely. 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?
Here is some information about how my code works.
I have a Akka FSM that waits for files to arrive. 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. When FSM receives that message it goes to a non-receiving state and does pushTODB work. 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. So everything hangs on the fact that I receive periodic PushTODB message.
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. 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.
Hope this code help to understand the problem.
..Manas