gocardless / statesman

A statesmanlike state machine library.
https://gocardless.com/blog/statesman/
MIT License
1.79k stars 163 forks source link

Update from 10.1.0 to 10.2.1 causing failures #509

Closed marclennox closed 10 months ago

marclennox commented 1 year ago

I recently tried updating our project and noticed a lot of test failures in our code as a direct result. I've debugged into the gem code and can't understand what is going on, but the following debug calls illustrate the issue.

[4] pry(#<RSpec::ExampleGroups::MonitoringSession::Callbacks::OnTerminate>)> subject.monitoring_state
=> "ready"
[5] pry(#<RSpec::ExampleGroups::MonitoringSession::Callbacks::OnTerminate>)> subject.monitoring_session_state_machine.current_state
=> "incomplete"

So basically when the state machine object is initialized in the subject class, it's not setting it to the object's current state (ActiveRecord adapter). Instead, it's setting the current state to the state machines's defined default initial_state.

This only happens with 10.2.1, works fine with 10.1.0

Has something changed that requires us to make changes to our use of the gem?

Thanks.

Paul-Yves commented 1 year ago

Same here, and the transition_to method returns true but the state did not change

zerc commented 1 year ago

Hello there

In version 10.2.x of Statesman, there is a bug fix for when the internal cache did not work for the initial transition.

The following example would produce different results in 10.1.x and 10.2.x:

subject = Subject.get("1")
subject.current_state == "initial"

subject_again = Subject.get("2")
subject_again.current_state == "initial"

subject.transition_to!("some_state")

# In 10.1.x this will be true for the initial transition and false for every other transition.
# In 10.2.x this will always be false.
subject.current_state == subject_again.current_state

It's important to note that this behavior already existed for all transitions and only did not work correctly for the initial transition. Consequently, if the code relied on this undocumented (incorrect) behavior, it would fail.

You would need to manually invalidate the cache by calling .state_machine.reset or, if you're using Statesman::Adapters::ActiveRecordQueries and the state_machine property, it will be done automatically for you when you call model.reload. See https://github.com/gocardless/statesman/issues/509.

If you provide an isolated example of your test case I may be able to assist in debugging the problem.