Provide API to return Is state machine has queued event
okhowang opened this issue · comments
I write a wrapper for stateless.StateMachine
.
for run some function after trigger succeed.
func (sm *State Machine) FireCtx(ctx context.Context, trigger stateless.Trigger, args ...interface{}) error {
if v, ok := ctx.Value(deferRunnerKey{}).(*deferRunner); !ok || v == nil {
ctx = context.WithValue(ctx, deferRunnerKey{}, &deferRunner{})
}
err := sm.StateMachine.FireCtx(ctx, trigger, args...)
if err == nil { // one more condition if trigger queued, defer function shouldn't be call
defers := ctx.Value(deferRunnerKey{}).(*deferRunner) // nolint:errcheck
for _, task := range defers.tasks {
task(ctx)
}
}
return err
}
but there is a bug when call Fire
in StateMachine
func TestDeferTwice(t *testing.T) {
counter := 0
sm := &StateMachine{stateless.NewStateMachine("A")}
sm.Configure("A").Permit("toB", "B").
OnExit(func(ctx context.Context, i ...interface{}) error {
addDeferRunner(ctx, func(ctx context.Context) {
counter++
})
return nil
})
sm.Configure("B").Permit("toC", "C").
OnEntry(func(ctx context.Context, i ...interface{}) error {
return sm.FireCtx(ctx, "toC")
}).
OnExit(func(ctx context.Context, i ...interface{}) error {
addDeferRunner(ctx, func(ctx context.Context) {
counter++
})
return nil
})
assert.Equal(t, 0, counter)
assert.NoError(t, sm.Fire("toB"))
assert.Equal(t, "C", sm.MustState())
assert.Equal(t, 2, counter) // error here 3 vs 2
}
but there is no api to get that is there any event pendding.
Can we provide a Firing() bool
for StateMachine
to indicate is StateMachine firing now?