geekq / workflow

Ruby finite-state-machine-inspired API for modeling workflow
MIT License
1.75k stars 207 forks source link

Optimistic locking blocks #208

Closed kirkbowers closed 5 years ago

kirkbowers commented 6 years ago

I've run into situations using this gem in which a race condition occurs. Two state transitions are attempted at about the same time that are incompatible with each other (that is, a transition between the two ending states is not legal, but effectively occurs as a result of the race condition). Optimistic locking is the safest way to handle such a race condition, but the existing version 1.3 of the gem circumvents validations by calling update_column, thus making the use of optimistic locking impossible. This PR provides a mechanism for choosing between the default update_column mechanism or using a two step attribute assignment followed by save! to allow validations to be performed.

Also, I've seen this gem used in a manner that one transition event handler callback method isn't suitable for all situations. If your code wants to create different side effects in different situations along with a state transition, and if you want those side effects to only occur if the state transition succeeds (it's a legal transaction and the data isn't stale), the cleanest way to handle that would be to pass a block to the transition and execute that block within the same transaction as the transition. This PR adds that capability.

I noticed that the master branch is on 1.3.0, but that version has never been published to rubygems. I bump the version in my PR to 1.4.0 to allow for snapshotting 1.3.

Thanks!