statesman 3.5.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/lib/statesman/adapters/active_record.rb +38 -2
- data/lib/statesman/machine.rb +3 -3
- data/lib/statesman/version.rb +1 -1
- data/lib/tasks/statesman.rake +1 -1
- data/spec/statesman/adapters/active_record_queries_spec.rb +34 -0
- data/spec/statesman/adapters/active_record_spec.rb +2 -0
- data/statesman.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5063951e126e3898569d97511ea5c89149122c3e
|
4
|
+
data.tar.gz: 888fcdc8b6bfbde03dbc4471fa3d84f58fd0871e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4f1b64670d9b94c53f65ef3ed7182be77388c732536906d7066db8e0970016ad1e0cec26148d62b5cd32719e446a253033da3b1e8dd5c0c5e813834715e032f
|
7
|
+
data.tar.gz: 8c5ab391235a0f4b073fee60eeea93c4752e9f5a2d71a6b05ba955cebfd5bae61921bf87ac9769a967db05439cd907e5de6be1fe5f8d5a45a80fc4588b722d9a
|
data/.circleci/config.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## v4.0.0, 22 February 2019
|
2
|
+
|
3
|
+
- Forces Statesman to use a new transactions with `requires_new: true` (https://github.com/gocardless/statesman/pull/249)
|
4
|
+
- Fixes an issue with `after_commit` transition blocks that where being
|
5
|
+
executed even if the transaction rolled back. ([patch](https://github.com/gocardless/statesman/pull/338) by [@matid](https://github.com/matid))
|
6
|
+
|
1
7
|
## v3.5.0, 2 November 2018
|
2
8
|
|
3
9
|
- Expose `most_recent_transition_join` - ActiveRecords `or` requires that both
|
@@ -25,6 +25,7 @@ module Statesman
|
|
25
25
|
elsif serialized && JSON_COLUMN_TYPES.include?(column_type)
|
26
26
|
raise IncompatibleSerializationError, transition_class.name
|
27
27
|
end
|
28
|
+
|
28
29
|
@transition_class = transition_class
|
29
30
|
@parent_model = parent_model
|
30
31
|
@observer = observer
|
@@ -36,6 +37,7 @@ module Statesman
|
|
36
37
|
create_transition(from.to_s, to.to_s, metadata)
|
37
38
|
rescue ::ActiveRecord::RecordNotUnique => e
|
38
39
|
raise TransitionConflictError, e.message if transition_conflict_error? e
|
40
|
+
|
39
41
|
raise
|
40
42
|
ensure
|
41
43
|
@last_transition = nil
|
@@ -70,18 +72,26 @@ module Statesman
|
|
70
72
|
|
71
73
|
transition = transitions_for_parent.build(transition_attributes)
|
72
74
|
|
73
|
-
::ActiveRecord::Base.transaction do
|
75
|
+
::ActiveRecord::Base.transaction(requires_new: true) do
|
74
76
|
@observer.execute(:before, from, to, transition)
|
75
77
|
unset_old_most_recent
|
76
78
|
transition.save!
|
77
79
|
@last_transition = transition
|
78
80
|
@observer.execute(:after, from, to, transition)
|
81
|
+
add_after_commit_callback(from, to, transition)
|
79
82
|
end
|
80
|
-
@observer.execute(:after_commit, from, to, transition)
|
81
83
|
|
82
84
|
transition
|
83
85
|
end
|
84
86
|
|
87
|
+
def add_after_commit_callback(from, to, transition)
|
88
|
+
::ActiveRecord::Base.connection.add_transaction_record(
|
89
|
+
ActiveRecordAfterCommitWrap.new do
|
90
|
+
@observer.execute(:after_commit, from, to, transition)
|
91
|
+
end,
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
85
95
|
def transitions_for_parent
|
86
96
|
@parent_model.send(@association_name)
|
87
97
|
end
|
@@ -147,5 +157,31 @@ module Statesman
|
|
147
157
|
params.merge(column => timestamp)
|
148
158
|
end
|
149
159
|
end
|
160
|
+
|
161
|
+
class ActiveRecordAfterCommitWrap
|
162
|
+
def initialize
|
163
|
+
@callback = Proc.new
|
164
|
+
@connection = ::ActiveRecord::Base.connection
|
165
|
+
end
|
166
|
+
|
167
|
+
# rubocop: disable Naming/PredicateName
|
168
|
+
def has_transactional_callbacks?
|
169
|
+
true
|
170
|
+
end
|
171
|
+
# rubocop: enable Naming/PredicateName
|
172
|
+
|
173
|
+
def committed!(*)
|
174
|
+
@callback.call
|
175
|
+
end
|
176
|
+
|
177
|
+
def before_committed!(*); end
|
178
|
+
|
179
|
+
def rolledback!(*); end
|
180
|
+
|
181
|
+
# Required for +transaction(requires_new: true)+
|
182
|
+
def add_to_transaction(*)
|
183
|
+
@connection.add_transaction_record(self)
|
184
|
+
end
|
185
|
+
end
|
150
186
|
end
|
151
187
|
end
|
data/lib/statesman/machine.rb
CHANGED
data/lib/statesman/version.rb
CHANGED
data/lib/tasks/statesman.rake
CHANGED
@@ -19,7 +19,7 @@ namespace :statesman do
|
|
19
19
|
batch_size = 500
|
20
20
|
|
21
21
|
parent_class.find_in_batches(batch_size: batch_size) do |models|
|
22
|
-
ActiveRecord::Base.transaction do
|
22
|
+
ActiveRecord::Base.transaction(requires_new: true) do
|
23
23
|
if Statesman::Adapters::ActiveRecord.database_supports_partial_indexes?
|
24
24
|
# Set all transitions' most_recent to FALSE
|
25
25
|
transition_class.where(parent_fk => models.map(&:id)).
|
@@ -168,4 +168,38 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
171
|
+
|
172
|
+
context "after_commit transactional integrity" do
|
173
|
+
before do
|
174
|
+
MyStateMachine.class_eval do
|
175
|
+
cattr_accessor(:after_commit_callback_executed) { false }
|
176
|
+
|
177
|
+
after_transition(from: :initial, to: :succeeded, after_commit: true) do
|
178
|
+
# This leaks state in a testable way if transactional integrity is broken.
|
179
|
+
MyStateMachine.after_commit_callback_executed = true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
after do
|
185
|
+
MyStateMachine.class_eval do
|
186
|
+
callbacks[:after_commit] = []
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
let!(:model) do
|
191
|
+
MyActiveRecordModel.create
|
192
|
+
end
|
193
|
+
|
194
|
+
# rubocop:disable RSpec/ExampleLength
|
195
|
+
it do
|
196
|
+
expect do
|
197
|
+
ActiveRecord::Base.transaction do
|
198
|
+
model.state_machine.transition_to!(:succeeded)
|
199
|
+
raise ActiveRecord::Rollback
|
200
|
+
end
|
201
|
+
end.to_not change(MyStateMachine, :after_commit_callback_executed)
|
202
|
+
end
|
203
|
+
# rubocop:enable RSpec/ExampleLength
|
204
|
+
end
|
171
205
|
end
|
@@ -227,6 +227,7 @@ describe Statesman::Adapters::ActiveRecord, active_record: true do
|
|
227
227
|
it "still has the old state" do
|
228
228
|
allow(observer).to receive(:execute) do |phase|
|
229
229
|
next unless phase == :before
|
230
|
+
|
230
231
|
expect(
|
231
232
|
model.transitions.where(most_recent: true).first.to_state,
|
232
233
|
).to eq("y")
|
@@ -240,6 +241,7 @@ describe Statesman::Adapters::ActiveRecord, active_record: true do
|
|
240
241
|
it "still has the old state" do
|
241
242
|
allow(observer).to receive(:execute) do |phase|
|
242
243
|
next unless phase == :after
|
244
|
+
|
243
245
|
expect(
|
244
246
|
model.transitions.where(most_recent: true).first.to_state,
|
245
247
|
).to eq("z")
|
data/statesman.gemspec
CHANGED
@@ -31,6 +31,6 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "rspec-its", "~> 1.1"
|
32
32
|
spec.add_development_dependency "rspec-rails", "~> 3.1"
|
33
33
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.0"
|
34
|
-
spec.add_development_dependency "sqlite3", "~> 1.3"
|
34
|
+
spec.add_development_dependency "sqlite3", "~> 1.3.6"
|
35
35
|
spec.add_development_dependency "timecop", "~> 0.9.1"
|
36
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statesman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ammeter
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
187
|
+
version: 1.3.6
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
194
|
+
version: 1.3.6
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: timecop
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|