Skip to content
This repository has been archived by the owner on Feb 25, 2024. It is now read-only.

Bug: Leaving nested paralell states when target is non-empty leads to inconsistent state #404

Open
blodow opened this issue Mar 2, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@blodow
Copy link

blodow commented Mar 2, 2023

Description

Consider this statemachine:
https://stately.ai/viz/f24c571d-0e9d-4562-9d18-d7a8f2a30890

The state machine contains two big states, ping and pong, and transitions PING and PONG between them. pong contains parallel states, one of which just flip/flops upon PING and PONG signals. The other state (idle) wants to leave pong and go to ping upon PING. That transition has the following problem: when the target (ping) contains no child state, the whole machine works as I would expect, with either ping or pong being active. If ping does have a child state (commentMe), the transition is taken, but the flipFlop.flip state is somehow also kept active, so now ping AND pong are active, even though they are not in parallel relationship. Triggering PING a second time does get us to the intended state.

Unless I missed something in the docs, the behavior of the statemachine, as linked, is broken IMO, but can be made to work by commenting the commentMe state.

Expected result

Leaving state with nested parallel states would make all parallel states inactive.

Actual result

In case of the transition target containing children, leaving the state with nested parallel states can leave some of these active.

Reproduction

https://stately.ai/viz/f24c571d-0e9d-4562-9d18-d7a8f2a30890

Additional context

No response

@blodow blodow added the bug Something isn't working label Mar 2, 2023
@blodow blodow changed the title Bug: Leaving nested paralell states when target is nested leads to inconsistent state Bug: Leaving nested paralell states when target is non-empty leads to inconsistent state Mar 2, 2023
@DeylEnergy
Copy link

DeylEnergy commented Mar 21, 2023

This behavior seems to be correct. When you in pong parallel state you have PING events in pong.flipFlop and in pong.stuff.idle, sending PING event to the machine sort of propagates it through the machine. Since there is PING event on both nodes, transition occurs in both of them. If you rename PING in pong.flipFlop to something else it will work correctly.

@blodow
Copy link
Author

blodow commented Mar 21, 2023

I think I understand your point, but I see two issues with this:

  1. how can it be valid that both ping and pong are active within gadget, when they are not parallel?
  2. why does the behavior change when ping does or does not contain the commentme child?

@DeylEnergy
Copy link

DeylEnergy commented Mar 22, 2023

(1) tried to transition between states programmatically (without interpretation) and found out that visualizer works differently, to be precise

const pongState = gadget.transition(gadget.initialState, {type: 'PONG'})
pongState.value // { pong: { stuff: idle, flipFlop: flop } }

const pingState = gadget.transition(pongState, {type: 'PING'})
pingState.value // { ping: {} }

interpret() behaves the same

const service = interpret(gadget)
service.start()

service.send({type: 'PONG'}).value // { pong: { stuff: idle, flipFlop: flop } }

service.send({type: 'PING'}).value // { ping: {} }

Also tried to pass actions to each PING event and within visualizer both of actions are get called, but outside of visualizer only stuff.idle's PING action is invoked.

(2) this one looks strange to me as well

@blodow
Copy link
Author

blodow commented Mar 24, 2023

Thanks @DeylEnergy for taking the time to look into this! It's great news that xstate seems to behave correctly outside of the visualizer. Would you recommend I open an issue with xstate-viz then?

@davidkpiano davidkpiano transferred this issue from statelyai/xstate Mar 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants