Double command invocation sends async iteration into a hanging state
Kelerchian opened this issue · comments
Alan Darmasaputra commented
This happens in test code
const ToggleOn = MachineEvent.design('ToggleOn').withoutPayload()
const ToggleOff = MachineEvent.design('ToggleOff').withoutPayload()
const protocol = SwarmProtocol.make('switch', [ToggleOn, ToggleOff])
const machine = protocol.makeMachine('switch')
type StatePayload = { toggleCount: number }
const On = machine
.designState('On')
.withPayload<StatePayload>()
.command('toggle', [ToggleOff], () => [{}])
.finish()
const Off = machine
.designState('Off')
.withPayload<StatePayload>()
.command('toggle', [ToggleOn], () => [{}])
.finish()
On.react([ToggleOff], Off, ({ self }) => ({ toggleCount: self.toggleCount + 1 }))
Off.react([ToggleOn], On, ({ self }) => ({ toggleCount: self.toggleCount + 1 }))
const r = new Runner(On, { toggleCount: 0 })
const machine = r.machine
r.feed([], true)
let toggleCount = 0
let iterationCount = 0
for await (const state of machine) {
iterationCount += 1
toggleCount =
state.as(On, (x) => x.payload.toggleCount) ||
state.as(Off, (x) => x.payload.toggleCount) ||
toggleCount
const whenOn = state.as(On)
if (whenOn) {
if (whenOn.payload.toggleCount > 0) {
break
}
await whenOn.commands?.toggle()
await whenOn.commands?.toggle()
}
const whenOff = state.as(Off)
if (whenOff) {
await whenOff.commands?.toggle()
}
}