Akka FSM Goto в будущем

Я пытаюсь изменить состояние FSM в будущем, но я не работаю. Я думаю, что ищу метод, похожий на pipeTo.

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 выполняется, но fsm не меняет состояние на State.Working

Я сам нашел эту работу

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
   }
}

Может быть, есть лучшая идея для решения проблемы


person Alexander Kondaurov    schedule 07.04.2015    source источник


Ответы (2)


Не изменяйте состояние вашего актера в будущем или что-либо вне основного «потока». Правильный способ решить вашу проблему - отправить себе сообщение, которое просто изменит состояние, например

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()
}
person M4ks    schedule 07.04.2015
comment
Но stay() сохранит состояние WaitingForResponse, верно? - person Martin Seeler; 27.07.2017
comment
да. Когда вы используете FSM в Akka, вы должны вернуть действие, которое вы выполняете, даже если оно неактивно. - person M4ks; 07.08.2017
comment
или используя узор трубы val f = asyncCode.map(res => if(res=1){ GoToWorking(Data.MyData) }else{ Stay }) ; f pipeTo self; goto(State.WaitingFOrResponse) - person Murat Mustafin; 07.09.2017

Вы никогда не должны закрывать и изменять состояние актера из асинхронного обратного вызова (например, комбинаторов Future). Это также верно для методов FSM, они являются частными для актора. Единственный способ, которым актор должен реагировать на асинхронные события, — это получать сообщение. Ваш второй код почти правильный, за исключением того, что вы даже не должны вызывать stay() из обратного вызова. Асинхронный результат должен заканчиваться сообщением, отправленным актору, который, в свою очередь, может изменить свое состояние. Возможно, вы захотите ввести новое состояние ожидания, в которое вы переходите при запуске асинхронного вызова, и после его завершения (актер получает результат) переходите к State.Working.

person Endre Varga    schedule 07.04.2015
comment
Приведенный ниже комментарий M4ks объясняет то же самое в деталях. - person Endre Varga; 07.04.2015
comment
Да, было, но с примером - person Alexander Kondaurov; 07.04.2015