Actyx / machines

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Double command invocation sends async iteration into a hanging state

Kelerchian opened this issue · comments

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()
  }
}