[statemachine] properly prevent transition when clearing error
This commit is contained in:
parent
59576e76d8
commit
1c0dc582bd
|
@ -51,7 +51,9 @@ proc schedule*(machine: Machine, event: Event) =
|
||||||
proc checkTransitions(machine: Machine) =
|
proc checkTransitions(machine: Machine) =
|
||||||
for transition in machine.transitions:
|
for transition in machine.transitions:
|
||||||
if transition.trigger(machine, machine.state) and
|
if transition.trigger(machine, machine.state) and
|
||||||
(machine.state == nil or machine.state == transition.prevState or transition.prevState of AnyState):
|
(machine.state == nil or
|
||||||
|
machine.state == transition.prevState or
|
||||||
|
transition.prevState of AnyState):
|
||||||
machine.schedule(Event.transition(machine.state, transition.nextState))
|
machine.schedule(Event.transition(machine.state, transition.nextState))
|
||||||
|
|
||||||
proc setValue*[T](prop: TransitionProperty[T], value: T) =
|
proc setValue*[T](prop: TransitionProperty[T], value: T) =
|
||||||
|
@ -74,7 +76,7 @@ proc scheduler(machine: Machine) {.async.} =
|
||||||
if fut.failed():
|
if fut.failed():
|
||||||
try:
|
try:
|
||||||
machine.errored.setValue(true) # triggers transitions
|
machine.errored.setValue(true) # triggers transitions
|
||||||
machine.errored.setValue(false) # clears error without triggering transitions
|
machine.errored.value = false # clears error without triggering transitions
|
||||||
machine.lastError = fut.error # stores error in state
|
machine.lastError = fut.error # stores error in state
|
||||||
except AsyncQueueFullError as e:
|
except AsyncQueueFullError as e:
|
||||||
error "Cannot set transition value because queue is full", error = e
|
error "Cannot set transition value because queue is full", error = e
|
||||||
|
|
|
@ -167,8 +167,7 @@ suite "async state machines":
|
||||||
|
|
||||||
test "checks declarative transitions after current state finishes running":
|
test "checks declarative transitions after current state finishes running":
|
||||||
machine.start(state4)
|
machine.start(state4)
|
||||||
machine.slotsFilled.setValue(2) # on wrong starting state, so stays on state4
|
machine.slotsFilled.setValue(2) # no trigger conditions met yet
|
||||||
await sleepAsync(1.millis)
|
|
||||||
# manually move to State3, where the trigger and the previous state will
|
# manually move to State3, where the trigger and the previous state will
|
||||||
# be checked
|
# be checked
|
||||||
machine.schedule(Event.transition(state4, state3))
|
machine.schedule(Event.transition(state4, state3))
|
||||||
|
@ -182,3 +181,28 @@ suite "async state machines":
|
||||||
check eventually machine.state of State5
|
check eventually machine.state of State5
|
||||||
check not machine.errored.value # errored state has been cleared
|
check not machine.errored.value # errored state has been cleared
|
||||||
check machine.lastError.msg == "some error"
|
check machine.lastError.msg == "some error"
|
||||||
|
|
||||||
|
test "schedules transitions in order of declaration":
|
||||||
|
var checked = false
|
||||||
|
machine = MyMachine.new(@[
|
||||||
|
Transition.new(
|
||||||
|
state3,
|
||||||
|
state4,
|
||||||
|
proc(m: Machine, s: State): bool =
|
||||||
|
MyMachine(m).slotsFilled.value == 2
|
||||||
|
),
|
||||||
|
Transition.new(
|
||||||
|
state3,
|
||||||
|
state5,
|
||||||
|
proc(m: Machine, s: State): bool =
|
||||||
|
checked = true
|
||||||
|
MyMachine(m).slotsFilled.value == 2
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
machine.slotsFilled = machine.newTransitionProperty(0)
|
||||||
|
machine.start(state3)
|
||||||
|
machine.slotsFilled.setValue(2)
|
||||||
|
check eventually runs == [0, 0, 1, 1, 0]
|
||||||
|
check machine.state of State4
|
||||||
|
check checked
|
||||||
|
#3->5 transition was checked but not run because state had already moved to 4
|
||||||
|
|
Loading…
Reference in New Issue