-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
interpreter.start does not follow transient transitions #1259
Comments
IMHO it makes sense that those are not resolved because |
Guess that makes sense. I've resorted to manually changing the initial state in my component tests and just calling |
@Andarist this behavior makes it very difficult to test machines. It seems that |
When it comes to testing you might want to only test states in which you actually can "pause" the execution - it seems that you are trying to test the logic of the always transitions but you can already do that indirectly~. After all, they should be executed whenever you enter a state with such transitions so to test them you have to enter such a state in one of the tests. To trigger those transitions you can also just do this: service.start(state)
service.send({ type: 'COMPLETELY_UNKNOWN' }) That being said - I will give this a second thought. The idea was that |
There are two sides to the story here.
I'm not a fan of wasting work but overall the cost of this is probably super negligible. OTOH, we want to make heavy use of rehydrating states on the backend, and everything matters™. We could somehow allow for both behaviors but that would increase the API surface and I'm not sold on the idea because it usually shouldn't matter and having one, clear, behavior is better than having two. The presented use case (testing) isn't that compelling to me, but I'm definitely somewhat biased here by my testing preferences. There are workarounds (as mentioned above) to achieve what you want in v4 - it ain't perfect but it should work. I think this is an interesting/unobvious problem and I don't want to diminish its importance - but it also didn't come up too often in the last 2 years. So I'm somewhat inclined to believe that this isn't a problem for the vast majority of our users. I would keep this issue open for a while, in an attempt to gather more community feedback about this. I'm open to changing this behavior but I also don't treat such changes lightly. Note that we plan to make the "rehydration algorithm" recursive and it's also not obvious how this would behave with it - in what order those always transitions should be taken in a bigger tree of actors? Top-down? Bottom-up? How to make such "startup" always transitions of sibling actors predictable? Do we need to temporarily block any parts of the library while rehydrating? |
We too were bitten by this issue. I think this is very unintuitive behavior. If I start at some state I expect the machine to work like normal; and for it to be the same as transitioning into that state. I.e. the argument passed to If the reasoning for this has to do with persisted states then I would suggest moving that to a more appropriate API, or to make this behavior configurable. |
Thanks for the feedback. I think it makes sense to immediately take any eventless transitions from a restored state, since it should be impossible for the state machine to be "stuck" in a transient state. Will propose a PR for this soon. |
Transient transitions are still driven by events. To perform a transition - we need an event that triggers it. It's not an implementation limitation but rather the API constraint: always: [
target: '.a',
actions: ({ event }) => {
event // ???
}
] We used to resolve transient transitions with The mental model for persisting+rehydrating is that it's as opaque to the consumer as possible. If you persist in state A then we just take off from that point. If you are thinking about testing scenarios in which you want to "mock" the state then perhaps we should have dedicated testing utilities for that. In them, we could do things like resolving transient transitions - given that the caller would provide some event that we should use for that. |
For the reasons mentioned above - this is not planned right now. I'm open to discussing concrete use cases that need this though. If you have any - please open a discussion thread. We want to help you out and we might decide later on that some options/APIs for this might be needed. They would be different ones though than what is proposed by this issue (following transient transitions after |
Description
When starting an interpreted machine in a state that contains a transient transition, this transition is not executed.
While developing a state machine with a delayed transition using TDD, I stumbled across the problem that delayed transitions in the "start" state are not executed by the interpreter. I tried to use a dynamic transient state as a workaround (like mentioned in #294 (comment)), but it seems like this transition is also not executed.
Expected Result
interpret(machine).start(transientState)
should follow the transient transitions.Actual Result
It does not.
Reproduction
https://codesandbox.io/s/dreamy-paper-062hz?file=/src/index.ts
console shows
restart
, expectedrestart
, thensending
, laterdone
Additional context
The text was updated successfully, but these errors were encountered: