Моделирование FSM через преобразователь Process1?
У меня есть конечный автомат, который я хотел бы смоделировать с использованием скалярного потока Process1.
Конечный автомат моделирует поток сообщений между клиентом и сервером.
Базовый набор типов данных может быть:
sealed trait ServerState
case object Disconnected extends ServerState
case object Authenticating extends ServerState
case object Idle extends ServerState
case object Busy extends ServerState
sealed trait Message
case object Query extends Message
case object StartupMessage extends Message
case object AuthenticationOk extends Message
case object QueryResponse extends Message
В моей голове это будет моделироваться Process1[I, O]
, где type I = Message
а также type O = scalaz.State[Message, ServerState]
,
Это похоже на туман - я вижу схему решения, но твердое определение его ускользает от меня.
В настоящее время у меня есть то, что выглядит так
type Transition = scalaz.State[Message, ServerState]
val connecting = Transition { StartupMessage => (StartupMessage, Authenticating) }
def fsm(state: Transition): Process1[Message, Transition] = {
Await [Message, Transition] { msg =>
case (connecting, AuthenticationOk) => Emit1(connecting)
}
}
Я знаю, что это неправильно, но я не могу понять, где должны жить переходные периоды.
Если Процесс примет Message
и вернуть физический ServerState
в то время как Process1
драйвер обрабатывает внутреннее состояние?
Я изо всех сил пытаюсь понять, как "нести" сообщение, которое не может быть выполнено в данный момент.
Пример:
1. Current ServerState = Disconnected
2. StateMachine gets Query Message
3. StateMachine must send StartupMessage, ServerState now equals = Authenticating
4. StateMachine receives AuthenticationOk, ServerState now equals Idle
5. StateMachine must now sends original query message, ServerState now equals Busy
6. StateMachine gets QueryResponse, ServerState now equals Idle
1 ответ
Я думаю, что вы должны быть в состоянии закодировать свой конечный автомат с помощью рекурсивного Process1[Message, Message]
как это
def fsm(state: ServerState): Process1[Message, Message] = {
receive1 { msg: Message =>
(msg, state) match {
case (Query, Disconnected) =>
emit(StartupMessage) fby fsm(Authenticating)
case (AuthenticationOk, Authenticating) =>
fsm(Idle)
...
}
}
}
Возможно, вы захотите выделить Message
s, что ваша машина принимает как события (для запуска переходов) и те, которые она излучает (как "действия"), имея Process1[InMessage, OutMessage]