qmuntal / stateless

Go library for creating finite state machines
BSD 2-Clause "Simplified" License
942 stars 49 forks source link

How to handle triggers that are allowed in all states #5

Open luxl opened 4 years ago

luxl commented 4 years ago

Hi, thanks for this great state machine library and I meent a problem when using it. I have a trigger named "shutdown machine", and it can be fired at any state, which will result in back to the very original state. How to implement this? Adding the trigger to every state?

qmuntal commented 4 years ago

Hi @luxl, there is no way to set a general trigger for all the states, so will have to do it one by one when defining the state machine.

Anyway, I'll consider this feature a nice to have for future versions.

floriaanpost commented 10 months ago

I know this is a long time ago, but you can also achieve this by using substates. See the test below as an example:

func TestOnOffSuperstates(t *testing.T) {
    fsm := stateless.NewStateMachine("on1")

    // configure the on superstate
    fsm.Configure("on").
        InitialTransition("on1").
        Permit("shutdown", "off")

    // configure the off superstate
    fsm.Configure("off").
        Permit("turn-on", "on")

    // configure on1, substate of on
    fsm.Configure("on1").
        SubstateOf("on")

    // configure on2, substate of on
    fsm.Configure("on2").
        SubstateOf("on")

    // we are on, firing shutdown should get us in the off state
    fsm.Fire("shutdown")

    if fsm.MustState() != "off" {
        t.Error("Expected state to be off")
    }

    // we are off, firing turn-on should get us in the on -> on1 state
    fsm.Fire("turn-on")
    if fsm.MustState() != "on1" {
        t.Error("Expected state to be on1")
    }
}

You still need to tell each substate that it is a sustate of on, but I think is more elegant than defining the trigger on every state.