Skip to content

Commit

Permalink
Merge pull request #73 from qmuntal/substatereentry
Browse files Browse the repository at this point in the history
Don't execute entry action when reentering a state from a super state trigger
  • Loading branch information
qmuntal authored Feb 25, 2024
2 parents 16bd277 + c95407a commit ef268b3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
4 changes: 4 additions & 0 deletions statemachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ func (sm *StateMachine) internalFireOne(ctx context.Context, trigger Trigger, ar
err = sm.handleTransitioningTrigger(ctx, representativeState, transition, args...)
}
case *transitioningTriggerBehaviour:
if source == t.Destination {
// If a trigger was found on a superstate that would cause unintended reentry, don't trigger.
break
}
transition := Transition{Source: source, Destination: t.Destination, Trigger: trigger}
err = sm.handleTransitioningTrigger(ctx, representativeState, transition, args...)
case *internalTriggerBehaviour:
Expand Down
25 changes: 25 additions & 0 deletions statemachine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1612,3 +1612,28 @@ func assertPanic(t *testing.T, f func()) {
}()
f()
}

func TestStateMachineWhenInSubstate_TriggerSuperStateTwiceToSameSubstate_DoesNotReenterSubstate(t *testing.T) {
sm := NewStateMachine(stateA)
var eCount = 0

sm.Configure(stateB).
OnEntry(func(_ context.Context, _ ...any) error {
eCount++
return nil
}).
SubstateOf(stateC)

sm.Configure(stateA).
SubstateOf(stateC)

sm.Configure(stateC).
Permit(triggerX, stateB)

sm.Fire(triggerX)
sm.Fire(triggerX)

if eCount != 1 {
t.Errorf("expected 1, got %d", eCount)
}
}

0 comments on commit ef268b3

Please sign in to comment.