public interface PersistentFSMBase<S,D,E> extends Actor, Listeners, ActorLogging
trait State case class One extends State case class Two extends State case class Data(i : Int) } class A extends Actor with FSM[A.State, A.Data] { import A._ startWith(One, Data(42)) when(One) { case Event(SomeMsg, Data(x)) => ... case Ev(SomeMsg) => ... // convenience when data not needed } when(Two, stateTimeout = 5 seconds) { ... } initialize() }
Within the partial function the following values are returned for effecting state transitions:
- stay
for staying in the same state
- stay using Data(...)
for staying in the same state, but with
different data
- stay forMax 5.millis
for staying with a state timeout; can be
combined with using
- goto(...)
for changing into a different state; also supports
using
and forMax
- stop
for terminating this FSM actor
Each of the above also supports the method replying(AnyRef)
for
sending a reply before changing state.
While changing state, custom handlers may be invoked which are registered
using onTransition
. This is meant to enable concentrating
different concerns in different places; you may choose to use
when
for describing the properties of a state, including of
course initiating transitions, but you can describe the transitions using
onTransition
to avoid having to duplicate that code among
multiple paths which lead to a transition:
onTransition { case Active -> _ => cancelTimer("activeTimer") }
Multiple such blocks are supported and all of them will be called, not only the first matching one.
Another feature is that other actors may subscribe for transition events by
sending a SubscribeTransitionCallback
message to this actor.
Stopping a listener without unregistering will not remove the listener from the
subscription list; use UnsubscribeTransitionCallback
before stopping
the listener.
State timeouts set an upper bound to the time which may pass before another message is received in the current state. If no external message is available, then upon expiry of the timeout a StateTimeout message is sent. Note that this message will only be received in the state for which the timeout was set and that any message received will cancel the timeout (possibly to be started again by the next transition).
Another feature is the ability to install and cancel single-shot as well as repeated timers which arrange for the sending of a user-specified message:
setTimer("tock", TockMsg, 1 second, true) // repeating setTimer("lifetime", TerminateMsg, 1 hour, false) // single-shot cancelTimer("tock") isTimerActive("tock")
This is an EXPERIMENTAL feature and is subject to change until it has received more real world testing.
Modifier and Type | Interface and Description |
---|---|
static class |
PersistentFSMBase.TransformHelper |
Actor.emptyBehavior$, Actor.ignoringBehavior$
Modifier and Type | Method and Description |
---|---|
void |
applyState(PersistentFSM.State<S,D,E> nextState) |
void |
cancelTimer(java.lang.String name) |
boolean |
debugEvent() |
PersistentFSM.Event$ |
Event() |
void |
handleTransition(S prev,
S next) |
void |
initialize()
Deprecated.
Removed from API, called internally. Since 2.4.5.
|
boolean |
isStateTimerActive() |
boolean |
isTimerActive(java.lang.String name) |
void |
logTermination(PersistentFSM.Reason reason)
By default
PersistentFSM.Failure is logged at error level and other reason
types are not logged. |
void |
makeTransition(PersistentFSM.State<S,D,E> nextState) |
D |
nextStateData() |
void |
onTermination(scala.PartialFunction<PersistentFSM.StopEvent<S,D>,scala.runtime.BoxedUnit> terminationHandler) |
void |
onTransition(scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> transitionHandler) |
void |
postStop()
User overridable callback.
|
void |
processEvent(PersistentFSM.Event<D> event,
java.lang.Object source) |
void |
processMsg(java.lang.Object value,
java.lang.Object source) |
scala.PartialFunction<java.lang.Object,scala.runtime.BoxedUnit> |
receive()
This defines the initial actor behavior, it must return a partial function
with the actor logic.
|
void |
register(S name,
scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> function,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout) |
void |
setStateTimeout(S state,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout) |
void |
setTimer(java.lang.String name,
java.lang.Object msg,
scala.concurrent.duration.FiniteDuration timeout,
boolean repeat) |
void |
startWith(S stateName,
D stateData,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
Set initial state.
|
D |
stateData() |
S |
stateName() |
scala.collection.Iterable<S> |
stateNames() |
PersistentFSM.StateTimeout$ |
StateTimeout()
This case object is received in case of a state timeout.
|
PersistentFSM.State<S,D,E> |
stay()
Produce "empty" transition descriptor.
|
PersistentFSM.State<S,D,E> |
stop()
Produce change descriptor to stop this FSM actor with reason "Normal".
|
PersistentFSM.State<S,D,E> |
stop(PersistentFSM.Reason reason)
Produce change descriptor to stop this FSM actor including specified reason.
|
PersistentFSM.State<S,D,E> |
stop(PersistentFSM.Reason reason,
D stateData)
Produce change descriptor to stop this FSM actor including specified reason.
|
PersistentFSM.StopEvent$ |
StopEvent() |
void |
terminate(PersistentFSM.State<S,D,E> nextState) |
scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> |
total2pf(scala.Function2<S,S,scala.runtime.BoxedUnit> transitionHandler) |
PersistentFSMBase.TransformHelper |
transform(scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> func) |
void |
when(S stateName,
scala.concurrent.duration.FiniteDuration stateTimeout,
scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> stateFunction)
Insert a new StateFunction at the end of the processing chain for the
given state.
|
void |
whenUnhandled(scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> stateFunction) |
aroundPostRestart, aroundPostStop, aroundPreRestart, aroundPreStart, aroundReceive, context, postRestart, preRestart, preStart, self, sender, supervisorStrategy, unhandled
gossip, listenerManagement, listeners
log
PersistentFSM.Event$ Event()
PersistentFSM.StopEvent$ StopEvent()
PersistentFSM.StateTimeout$ StateTimeout()
void when(S stateName, scala.concurrent.duration.FiniteDuration stateTimeout, scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> stateFunction)
stateName
- designator for the statestateTimeout
- default state timeout for this statestateFunction
- partial function describing response to inputvoid startWith(S stateName, D stateData, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
initialize()
method.
If different state is needed after a restart this method, followed by initialize()
, can
be used in the actor life cycle hooks Actor.preStart()
and Actor.postRestart(java.lang.Throwable)
.
stateName
- initial state designatorstateData
- initial state datatimeout
- state timeout for the initial state, overriding the default timeout for that statePersistentFSM.State<S,D,E> stay()
No transition event will be triggered by stay()
.
If you want to trigger an event like S -> S
for onTransition
to handle use goto
instead.
PersistentFSM.State<S,D,E> stop()
PersistentFSM.State<S,D,E> stop(PersistentFSM.Reason reason)
reason
- (undocumented)PersistentFSM.State<S,D,E> stop(PersistentFSM.Reason reason, D stateData)
reason
- (undocumented)stateData
- (undocumented)PersistentFSMBase.TransformHelper transform(scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> func)
void setTimer(java.lang.String name, java.lang.Object msg, scala.concurrent.duration.FiniteDuration timeout, boolean repeat)
void cancelTimer(java.lang.String name)
boolean isTimerActive(java.lang.String name)
void setStateTimeout(S state, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
boolean isStateTimerActive()
void onTransition(scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> transitionHandler)
scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> total2pf(scala.Function2<S,S,scala.runtime.BoxedUnit> transitionHandler)
void onTermination(scala.PartialFunction<PersistentFSM.StopEvent<S,D>,scala.runtime.BoxedUnit> terminationHandler)
void whenUnhandled(scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> stateFunction)
void initialize()
S stateName()
D stateData()
scala.collection.Iterable<S> stateNames()
D nextStateData()
boolean debugEvent()
void register(S name, scala.PartialFunction<PersistentFSM.Event<D>,PersistentFSM.State<S,D,E>> function, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
scala.PartialFunction<java.lang.Object,scala.runtime.BoxedUnit> receive()
Actor
void processMsg(java.lang.Object value, java.lang.Object source)
void processEvent(PersistentFSM.Event<D> event, java.lang.Object source)
void applyState(PersistentFSM.State<S,D,E> nextState)
void makeTransition(PersistentFSM.State<S,D,E> nextState)
void postStop()
Actor
void terminate(PersistentFSM.State<S,D,E> nextState)
void logTermination(PersistentFSM.Reason reason)
PersistentFSM.Failure
is logged at error level and other reason
types are not logged. It is possible to override this behavior.reason
- (undocumented)