diff --git a/statemachine.go b/statemachine.go index 99e4c2a..6e7f54e 100644 --- a/statemachine.go +++ b/statemachine.go @@ -29,6 +29,7 @@ type Transition struct { Source State Destination State Trigger Trigger + Arguments []interface{} isInitial bool } @@ -344,13 +345,13 @@ func (sm *StateMachine) internalFireOne(ctx context.Context, trigger Trigger, ar case *ignoredTriggerBehaviour: // ignored case *reentryTriggerBehaviour: - transition := Transition{Source: source, Destination: t.Destination, Trigger: trigger} + transition := Transition{Source: source, Destination: t.Destination, Trigger: trigger, Arguments: args} err = sm.handleReentryTrigger(ctx, representativeState, transition, args...) case *dynamicTriggerBehaviour: var destination any destination, err = t.Destination(ctx, args...) if err == nil { - transition := Transition{Source: source, Destination: destination, Trigger: trigger} + transition := Transition{Source: source, Destination: destination, Trigger: trigger, Arguments: args} err = sm.handleTransitioningTrigger(ctx, representativeState, transition, args...) } case *transitioningTriggerBehaviour: @@ -358,13 +359,13 @@ func (sm *StateMachine) internalFireOne(ctx context.Context, trigger Trigger, ar // 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} + transition := Transition{Source: source, Destination: t.Destination, Trigger: trigger, Arguments: args} err = sm.handleTransitioningTrigger(ctx, representativeState, transition, args...) case *internalTriggerBehaviour: var sr *stateRepresentation sr, err = sm.currentState(ctx) if err == nil { - transition := Transition{Source: source, Destination: source, Trigger: trigger} + transition := Transition{Source: source, Destination: source, Trigger: trigger, Arguments: args} err = sr.InternalAction(ctx, transition, args...) } } @@ -377,7 +378,7 @@ func (sm *StateMachine) handleReentryTrigger(ctx context.Context, sr *stateRepre } newSr := sm.stateRepresentation(transition.Destination) if !transition.IsReentry() { - transition = Transition{Source: transition.Destination, Destination: transition.Destination, Trigger: transition.Trigger} + transition = Transition{Source: transition.Destination, Destination: transition.Destination, Trigger: transition.Trigger, Arguments: args} if err := newSr.Exit(ctx, transition, args...); err != nil { return err } @@ -413,7 +414,7 @@ func (sm *StateMachine) handleTransitioningTrigger(ctx context.Context, sr *stat return err } } - callEvents(sm.onTransitionedEvents, ctx, Transition{transition.Source, rep.State, transition.Trigger, false}) + callEvents(sm.onTransitionedEvents, ctx, Transition{transition.Source, rep.State, transition.Trigger, args, false}) return nil } @@ -437,9 +438,9 @@ func (sm *StateMachine) enterState(ctx context.Context, sr *stateRepresentation, if !isValidForInitialState { panic(fmt.Sprintf("stateless: The target (%v) for the initial transition is not a substate.", sr.InitialTransitionTarget)) } - initialTranslation := Transition{Source: transition.Source, Destination: sr.InitialTransitionTarget, Trigger: transition.Trigger, isInitial: true} + initialTranslation := Transition{Source: transition.Source, Destination: sr.InitialTransitionTarget, Trigger: transition.Trigger, isInitial: true, Arguments: args} sr = sm.stateRepresentation(sr.InitialTransitionTarget) - callEvents(sm.onTransitioningEvents, ctx, Transition{transition.Destination, initialTranslation.Destination, transition.Trigger, false}) + callEvents(sm.onTransitioningEvents, ctx, Transition{transition.Destination, initialTranslation.Destination, transition.Trigger, args, false}) sr, err = sm.enterState(ctx, sr, initialTranslation, args...) } return sr, err diff --git a/statemachine_test.go b/statemachine_test.go index a89718e..fb89cd5 100644 --- a/statemachine_test.go +++ b/statemachine_test.go @@ -26,8 +26,8 @@ func TestTransition_IsReentry(t *testing.T) { t *Transition want bool }{ - {"TransitionIsNotChange", &Transition{"1", "1", "0", false}, true}, - {"TransitionIsChange", &Transition{"1", "2", "0", false}, false}, + {"TransitionIsNotChange", &Transition{"1", "1", "0", nil, false}, true}, + {"TransitionIsChange", &Transition{"1", "2", "0", nil, false}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/states_test.go b/states_test.go index 6cd993d..efb2c57 100644 --- a/states_test.go +++ b/states_test.go @@ -218,15 +218,15 @@ func Test_stateRepresentation_Enter_EnteringActionsExecuted_Error(t *testing.T) func Test_stateRepresentation_Enter_LeavingActionsNotExecuted(t *testing.T) { sr := newstateRepresentation(stateA) transition := Transition{Source: stateA, Destination: stateB, Trigger: triggerX} - var actualTransition Transition + var actualTransition *Transition sr.ExitActions = append(sr.ExitActions, actionBehaviour{ Action: func(_ context.Context, _ ...any) error { - actualTransition = transition + actualTransition = &transition return nil }, }) sr.Enter(context.Background(), transition) - if actualTransition != (Transition{}) { + if actualTransition != nil { t.Error("expected transition to not be passed to action") } } @@ -329,15 +329,15 @@ func Test_stateRepresentation_Enter_Substate_SuperstateEntryActionsExecuteBefore func Test_stateRepresentation_Exit_EnteringActionsNotExecuted(t *testing.T) { sr := newstateRepresentation(stateB) transition := Transition{Source: stateA, Destination: stateB, Trigger: triggerX} - var actualTransition Transition + var actualTransition *Transition sr.EntryActions = append(sr.EntryActions, actionBehaviour{ Action: func(_ context.Context, _ ...any) error { - actualTransition = transition + actualTransition = &transition return nil }, }) sr.Exit(context.Background(), transition) - if actualTransition != (Transition{}) { + if actualTransition != nil { t.Error("expected transition to not be passed to action") } } @@ -345,17 +345,17 @@ func Test_stateRepresentation_Exit_EnteringActionsNotExecuted(t *testing.T) { func Test_stateRepresentation_Exit_LeavingActionsExecuted(t *testing.T) { sr := newstateRepresentation(stateA) transition := Transition{Source: stateA, Destination: stateB, Trigger: triggerX} - var actualTransition Transition + var actualTransition *Transition sr.ExitActions = append(sr.ExitActions, actionBehaviour{ Action: func(_ context.Context, _ ...any) error { - actualTransition = transition + actualTransition = &transition return nil }, }) if err := sr.Exit(context.Background(), transition); err != nil { t.Error(err) } - if actualTransition != transition { + if actualTransition != &transition { t.Error("expected transition to be passed to leaving actions") } } @@ -363,7 +363,7 @@ func Test_stateRepresentation_Exit_LeavingActionsExecuted(t *testing.T) { func Test_stateRepresentation_Exit_LeavingActionsExecuted_Error(t *testing.T) { sr := newstateRepresentation(stateA) transition := Transition{Source: stateA, Destination: stateB, Trigger: triggerX} - var actualTransition Transition + var actualTransition *Transition sr.ExitActions = append(sr.ExitActions, actionBehaviour{ Action: func(_ context.Context, _ ...any) error { return errors.New("") @@ -372,7 +372,7 @@ func Test_stateRepresentation_Exit_LeavingActionsExecuted_Error(t *testing.T) { if err := sr.Exit(context.Background(), transition); err == nil { t.Error("expected error") } - if actualTransition == transition { + if actualTransition == &transition { t.Error("expected transition to not be passed to leaving actions") } }