Search code examples
scalaakkafsm

Akka FSM Goto within future


I'm trying to change FSM state in future but i doesn't work.. I think i'm looking for pipeTo like method.

When(State.Waiting) {
   case Event(anyMsg, anyData) =>
      asyncCode.map(res =>
         if (res == 1) {
            goto(State.Working) using Data.MyData
         } else {
            stay() replying "bad response"
         }

      )
}

goto command gets executed but fsm doesn't change state to State.Working

I found this work around by myself

When(State.Waiting) {
   case Event(anyMsg, anyData) =>
      asyncCode.map(res =>
         if (res == 1) {
            self ! "do job"
         } else {
            stay() replying "bad response"
         }

      )
   case Event("do job", anyData) => {
      goto(State.Working) using Data.MyData
   }
}

May be there is a better idea to solve problem


Solution

  • Do not change the state of your actor in the future or anything not inside the main "thread". The correct way to solve your problem is to send a message to self which will just change the state, like

    When(State.Waiting) {
      case Event(anyMsg, anyData) =>
        asyncCode.map(res =>
          if (res == 1) {
            self ! GoToWorking(Data.MyData)
          } else {
            self ! Stay
          }
        )
        goto(State.WaitingForResponse)
    }
    
    When (State.WaitingForResponse) {
      case Event(GoToWorking(data), _) =>
        goto(State.Working) using data
      case Event(Stay,_) =>
        stay()
    }