state_machine_job 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +7 -16
- data/Gemfile +0 -3
- data/README.md +10 -15
- data/lib/state_machine_job.rb +17 -30
- data/lib/state_machine_job/macro.rb +9 -21
- data/lib/state_machine_job/version.rb +1 -1
- data/spec/spec_helper.rb +8 -2
- data/spec/state_machine_job/macro_spec.rb +118 -146
- data/spec/state_machine_job_spec.rb +32 -86
- data/state_machine_job.gemspec +7 -6
- metadata +39 -21
- data/spec/support/setup_resque_logger.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7321f4a9acadaf04e7ae9e042984c0236a515d75afb4fa4c099285c8fa315081
|
4
|
+
data.tar.gz: 7cb0105c55838f3d0e2814ccb5c0e2e867d787b81ab3c04ca90eef416f69bb63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32a5ee63e8d498fcc5457700f554451b02b243069d9ff92f22cebe96f1382e31030c775a3ddf5a45bc9db36174098dba177206b8cfd1fa568e5fce024e7b7c98
|
7
|
+
data.tar.gz: cecc86f4fc4dbdc206128251c2cb987f68ff392128397682f8f535970c8c9ed7a0c7de234dc0f745a04806db79fec298b91b743a2ae6f5e2d7f897e690a805ce
|
data/CHANGELOG.md
CHANGED
@@ -1,24 +1,15 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
### Version
|
3
|
+
### Version 2.0.0
|
4
4
|
|
5
|
-
|
5
|
+
2018-07-27
|
6
6
|
|
7
|
-
[Compare changes](http://github.com/codevise/state_machine_job/compare/
|
7
|
+
[Compare changes](http://github.com/codevise/state_machine_job/compare/1-x-stable...v2.0.0)
|
8
8
|
|
9
|
-
-
|
10
|
-
|
11
|
-
|
12
|
-
free to rescue exceptions themselves and return an error result
|
13
|
-
instead.
|
14
|
-
([#5](https://github.com/codevise/state_machine_job/pull/5))
|
15
|
-
- Add backtrace info to exception logging
|
16
|
-
([#3](https://github.com/codevise/state_machine_job/pull/3))
|
17
|
-
- Restrict activesupport to < 5 for now
|
18
|
-
([#4](https://github.com/codevise/state_machine_job/pull/4))
|
19
|
-
- Use sinatra 1 in development and tests for ruby 2.1 compatibility
|
20
|
-
([#6](https://github.com/codevise/state_machine_job/pull/6))
|
9
|
+
- Breaking change: Decouple from Resque and use Active Job. See README
|
10
|
+
for updated usage instructions.
|
11
|
+
([#9](https://github.com/codevise/state_machine_job/pull/9))
|
21
12
|
|
22
13
|
See
|
23
|
-
[
|
14
|
+
[1-x-stable branch](http://github.com/codevise/state_machine_job/blob/1-x-stable/CHANGELOG.md)
|
24
15
|
for previous changes.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
[](http://badge.fury.io/rb/state_machine_job)
|
4
4
|
[](https://travis-ci.org/codevise/state_machine_job)
|
5
5
|
|
6
|
-
Enqueue
|
7
|
-
|
6
|
+
Enqueue jobs on state machine transitions and change state according
|
7
|
+
to job result.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -12,19 +12,15 @@ Add this line to your application's Gemfile:
|
|
12
12
|
|
13
13
|
gem 'state_machine_job'
|
14
14
|
|
15
|
-
Requires the [resque-logger](https://github.com/salizzar/resque-logger)
|
16
|
-
gem to be present and configured.
|
17
|
-
|
18
15
|
## Usage
|
19
16
|
|
20
|
-
|
21
|
-
`perform_with_result`
|
22
|
-
method:
|
17
|
+
Include the `StateMachineJob` mixin in your job and provide a
|
18
|
+
`perform_with_result` method instead of the normal `perform` method:
|
23
19
|
|
24
|
-
class SomeJob
|
25
|
-
|
20
|
+
class SomeJob < ApplicationJob
|
21
|
+
include StateMachineJob
|
26
22
|
|
27
|
-
def
|
23
|
+
def perform_with_result(record, payload)
|
28
24
|
# do something
|
29
25
|
:ok
|
30
26
|
end
|
@@ -61,8 +57,8 @@ event or by manually updateing the attribute), `SomeJob` will
|
|
61
57
|
automatically be enqueued. If `perform_with_result` returns `:ok`, the
|
62
58
|
state machine transitions to the `'done'` state. You can specify as
|
63
59
|
many results as you want. Note that any exception raised by
|
64
|
-
`perform_with_result`
|
65
|
-
`:error`.
|
60
|
+
`perform_with_result` leads to a state machine transition as if the
|
61
|
+
result had been `:error`. The exception is not rescued, though.
|
66
62
|
|
67
63
|
### Passing custom Payload
|
68
64
|
|
@@ -117,8 +113,7 @@ You can tell the state machine to retry a job based on its result:
|
|
117
113
|
|
118
114
|
When `perform_with_result` returns the result `:pending`, the state
|
119
115
|
machine will remain in the `runnning` state and enqueue a delayed
|
120
|
-
job. This
|
121
|
-
gem.
|
116
|
+
job. This feature uses the Active Job `set(wait: n)` functionality.
|
122
117
|
|
123
118
|
### Retrying Jobs Based on State
|
124
119
|
|
data/lib/state_machine_job.rb
CHANGED
@@ -1,40 +1,27 @@
|
|
1
1
|
require 'state_machine_job/version'
|
2
2
|
require 'state_machine_job/macro'
|
3
3
|
|
4
|
-
require 'resque'
|
5
|
-
require 'resque/plugins/logger'
|
6
|
-
require 'resque_logger'
|
7
|
-
|
8
4
|
module StateMachineJob
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
logger.error "#{self.name} - exception for #{model_name} #{id}: #{e.inspect}"
|
23
|
-
e.backtrace.each { |line| logger.info(line) }
|
24
|
-
|
25
|
-
raise
|
26
|
-
ensure
|
27
|
-
logger.info "#{self.name} - result #{result} for #{model_name} #{id}"
|
28
|
-
record.send(event_name(result))
|
29
|
-
end
|
30
|
-
else
|
31
|
-
logger.info "#{self.name} - #{model_name} #{id} not found. Skipping job."
|
5
|
+
def perform(record, payload = {})
|
6
|
+
record_name = "#{record.class.name} #{record.id}"
|
7
|
+
logger.info "perform for #{record_name}"
|
8
|
+
|
9
|
+
begin
|
10
|
+
result = perform_with_result(record, payload)
|
11
|
+
rescue StandardError
|
12
|
+
result = :error
|
13
|
+
raise
|
14
|
+
ensure
|
15
|
+
logger.info "result #{result} for #{record_name}"
|
16
|
+
record.send(StateMachineJob.result_method_name(self.class, result))
|
32
17
|
end
|
33
18
|
end
|
34
19
|
|
35
|
-
|
20
|
+
def self.result_event_name(job, result)
|
21
|
+
[job.name.underscore.split('/'), result].flatten.join('_').to_sym
|
22
|
+
end
|
36
23
|
|
37
|
-
def
|
38
|
-
(
|
24
|
+
def self.result_method_name(job, result)
|
25
|
+
"#{result_event_name(job, result)}!"
|
39
26
|
end
|
40
27
|
end
|
@@ -1,15 +1,14 @@
|
|
1
1
|
module StateMachineJob
|
2
2
|
module Macro
|
3
|
-
def job(job_class,
|
4
|
-
|
3
|
+
def job(job_class, &block)
|
4
|
+
JobDSL.new(job_class, self).instance_eval(&block)
|
5
5
|
end
|
6
6
|
|
7
|
-
class
|
8
|
-
def initialize(job, state_machine
|
7
|
+
class JobDSL
|
8
|
+
def initialize(job, state_machine)
|
9
9
|
@job = job
|
10
10
|
@state_machine = state_machine
|
11
|
-
@
|
12
|
-
@payload = lambda do |*args|
|
11
|
+
@payload = lambda do |*|
|
13
12
|
{}
|
14
13
|
end
|
15
14
|
end
|
@@ -38,7 +37,7 @@ module StateMachineJob
|
|
38
37
|
on_enter_state = @on_enter_state
|
39
38
|
|
40
39
|
if options[:state]
|
41
|
-
@state_machine.event(
|
40
|
+
@state_machine.event(StateMachineJob.result_event_name(@job, job_result)) do
|
42
41
|
if options[:retry_if_state]
|
43
42
|
transition options[:retry_if_state] => on_enter_state
|
44
43
|
end
|
@@ -46,34 +45,23 @@ module StateMachineJob
|
|
46
45
|
transition(all => options[:state], :if => options[:if])
|
47
46
|
end
|
48
47
|
elsif options[:retry_after]
|
49
|
-
@state_machine.define_helper :instance,
|
50
|
-
@
|
48
|
+
@state_machine.define_helper :instance, StateMachineJob.result_method_name(@job, job_result) do |_machine, object|
|
49
|
+
@job.set(wait: options[:retry_after]).perform_later(object, @payload.call(object))
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
54
|
def on_enter(state)
|
56
|
-
job, state_machine, queue = @job, @state_machine, @queue
|
57
55
|
@on_enter_state = state
|
58
56
|
|
59
57
|
@state_machine.after_transition @state_machine.any => state do |object|
|
60
|
-
|
58
|
+
@job.perform_later(object, @payload.call(object))
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
62
|
def payload(&block)
|
65
63
|
@payload = block
|
66
64
|
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def retry_job_method_name(result)
|
71
|
-
"#{job_result_event_name(result)}!"
|
72
|
-
end
|
73
|
-
|
74
|
-
def job_result_event_name(result)
|
75
|
-
[@job.name.underscore.split('/'), result].flatten.join('_').to_sym
|
76
|
-
end
|
77
65
|
end
|
78
66
|
end
|
79
67
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'action_controller/railtie'
|
2
|
+
require 'rspec/rails'
|
2
3
|
|
3
4
|
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
|
4
5
|
$LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
|
5
6
|
|
6
7
|
require 'active_support/inflector'
|
8
|
+
require 'active_model'
|
9
|
+
require 'active_job'
|
7
10
|
require 'state_machine'
|
8
11
|
require 'state_machine_job'
|
9
12
|
|
10
|
-
|
13
|
+
ActiveJob::Base.logger = Logger.new(nil)
|
14
|
+
ActiveJob::Base.queue_adapter = :test
|
15
|
+
|
16
|
+
GlobalID.app = :test
|
@@ -1,100 +1,109 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
require 'rspec/rails/matchers/active_job'
|
4
|
+
require 'timecop'
|
5
|
+
|
3
6
|
module StateMachineJob
|
4
7
|
describe Macro do
|
5
|
-
class TestJob
|
8
|
+
class TestJob < ActiveJob::Base
|
9
|
+
include StateMachineJob
|
6
10
|
end
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
attr_accessor :some_attribute
|
12
|
+
class BaseModel
|
13
|
+
include ActiveModel::Model
|
14
|
+
include GlobalID::Identification
|
12
15
|
|
13
|
-
|
14
|
-
self.some_attribute = some_attribute
|
15
|
-
super()
|
16
|
-
end
|
16
|
+
attr_accessor :id
|
17
17
|
|
18
|
-
|
19
|
-
43
|
20
|
-
end
|
18
|
+
cattr_accessor :instances
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
def initialize(*)
|
21
|
+
super
|
22
|
+
instances[id] = self
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def self.find(id)
|
26
|
+
instances.fetch(id.to_i)
|
27
|
+
end
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
before do
|
31
|
+
BaseModel.instances = {}
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
class Model < BaseModel
|
35
|
+
attr_accessor :state, :some_attribute
|
36
|
+
|
37
|
+
state_machine initial: :idle do
|
38
|
+
extend StateMachineJob::Macro
|
39
|
+
|
40
|
+
state :idle
|
41
|
+
state :running
|
42
|
+
state :done
|
43
|
+
state :failed
|
44
|
+
|
45
|
+
event :run do
|
46
|
+
transition idle: :running
|
47
|
+
end
|
48
|
+
|
49
|
+
job TestJob do
|
50
|
+
on_enter :running
|
51
|
+
payload do |record|
|
52
|
+
{some_attribute: record.some_attribute}
|
40
53
|
end
|
54
|
+
result ok: :done
|
41
55
|
end
|
42
56
|
end
|
43
|
-
|
57
|
+
end
|
44
58
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
59
|
+
it 'enques job with record and payload arguments when entering on_enter state' do
|
60
|
+
record = Model.new(id: 5, some_attribute: 'value')
|
48
61
|
|
49
|
-
expect(queue).to receive(:enqueue).with(TestJob, 'Model', 43, {:some_attribute => 'value'})
|
50
62
|
record.run
|
51
|
-
end
|
52
63
|
|
53
|
-
|
54
|
-
|
55
|
-
model = Class.new do
|
56
|
-
attr_accessor :some_attribute
|
64
|
+
expect(TestJob).to have_been_enqueued.with(record, some_attribute: 'value')
|
65
|
+
end
|
57
66
|
|
58
|
-
|
59
|
-
|
60
|
-
super()
|
61
|
-
end
|
67
|
+
class ModelWithRetry < BaseModel
|
68
|
+
attr_accessor :state, :some_attribute
|
62
69
|
|
63
|
-
|
64
|
-
|
65
|
-
end
|
70
|
+
state_machine initial: :idle do
|
71
|
+
extend StateMachineJob::Macro
|
66
72
|
|
67
|
-
|
68
|
-
|
73
|
+
state :idle
|
74
|
+
state :running
|
75
|
+
state :done
|
76
|
+
state :failed
|
69
77
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
state :failed
|
78
|
+
event :run do
|
79
|
+
transition idle: :running
|
80
|
+
end
|
74
81
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
result :failed, :retry_after => 60
|
81
|
-
result :ok => :done
|
82
|
+
job TestJob do
|
83
|
+
on_enter :running
|
84
|
+
payload do |record|
|
85
|
+
{some_attribute: record.some_attribute}
|
82
86
|
end
|
87
|
+
result ok: :done
|
88
|
+
result :failed, retry_after: 60
|
83
89
|
end
|
84
90
|
end
|
85
|
-
|
91
|
+
end
|
86
92
|
|
87
|
-
|
88
|
-
|
89
|
-
|
93
|
+
it 'enques job after retry time with record and payload when result event is invoked' do
|
94
|
+
Timecop.freeze do
|
95
|
+
record = ModelWithRetry.new(id: 5, some_attribute: 'value')
|
96
|
+
|
97
|
+
record.state_machine_job_test_job_failed!
|
90
98
|
|
91
|
-
|
92
|
-
|
99
|
+
expect(TestJob).to have_been_enqueued
|
100
|
+
.at(60.seconds.from_now).with(record, some_attribute: 'value')
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
it 'has event for job result which transitions to result state' do
|
96
105
|
object = Class.new do
|
97
|
-
state_machine :
|
106
|
+
state_machine initial: :idle do
|
98
107
|
extend StateMachineJob::Macro
|
99
108
|
|
100
109
|
state :idle
|
@@ -103,12 +112,12 @@ module StateMachineJob
|
|
103
112
|
state :failed
|
104
113
|
|
105
114
|
event :run do
|
106
|
-
transition :
|
115
|
+
transition idle: :running
|
107
116
|
end
|
108
117
|
|
109
118
|
job TestJob do
|
110
119
|
on_enter :running
|
111
|
-
result :
|
120
|
+
result ok: :done
|
112
121
|
end
|
113
122
|
end
|
114
123
|
end.new
|
@@ -121,7 +130,7 @@ module StateMachineJob
|
|
121
130
|
|
122
131
|
it 'result supports state option signature' do
|
123
132
|
object = Class.new do
|
124
|
-
state_machine :
|
133
|
+
state_machine initial: :idle do
|
125
134
|
extend StateMachineJob::Macro
|
126
135
|
|
127
136
|
state :idle
|
@@ -129,12 +138,12 @@ module StateMachineJob
|
|
129
138
|
state :done
|
130
139
|
|
131
140
|
event :run do
|
132
|
-
transition :
|
141
|
+
transition idle: :running
|
133
142
|
end
|
134
143
|
|
135
144
|
job TestJob do
|
136
145
|
on_enter :running
|
137
|
-
result :ok, :
|
146
|
+
result :ok, state: :done
|
138
147
|
end
|
139
148
|
end
|
140
149
|
end.new
|
@@ -148,12 +157,12 @@ module StateMachineJob
|
|
148
157
|
it 'result raises descriptive error when trying to use hash only signature with additional options' do
|
149
158
|
expect {
|
150
159
|
Class.new do
|
151
|
-
state_machine :
|
160
|
+
state_machine initial: :idle do
|
152
161
|
extend StateMachineJob::Macro
|
153
162
|
|
154
163
|
job TestJob do
|
155
164
|
on_enter :running
|
156
|
-
result :
|
165
|
+
result ok: :done, if: true
|
157
166
|
end
|
158
167
|
end
|
159
168
|
end
|
@@ -162,13 +171,8 @@ module StateMachineJob
|
|
162
171
|
|
163
172
|
describe ':if option' do
|
164
173
|
it 'allows skipping matching results' do
|
165
|
-
queue = double('queue')
|
166
174
|
object = Class.new do
|
167
|
-
|
168
|
-
43
|
169
|
-
end
|
170
|
-
|
171
|
-
state_machine :initial => :idle do
|
175
|
+
state_machine initial: :idle do
|
172
176
|
extend StateMachineJob::Macro
|
173
177
|
|
174
178
|
state :idle
|
@@ -177,13 +181,13 @@ module StateMachineJob
|
|
177
181
|
state :other
|
178
182
|
|
179
183
|
event :run do
|
180
|
-
transition :
|
184
|
+
transition idle: :running
|
181
185
|
end
|
182
186
|
|
183
|
-
job TestJob
|
187
|
+
job TestJob do
|
184
188
|
on_enter :running
|
185
|
-
result :ok, :
|
186
|
-
result :ok, :
|
189
|
+
result :ok, state: :done, if: -> { false }
|
190
|
+
result :ok, state: :other
|
187
191
|
end
|
188
192
|
end
|
189
193
|
end.new
|
@@ -195,13 +199,8 @@ module StateMachineJob
|
|
195
199
|
end
|
196
200
|
|
197
201
|
it 'uses matching results if condition is truthy' do
|
198
|
-
queue = double('queue')
|
199
202
|
object = Class.new do
|
200
|
-
|
201
|
-
43
|
202
|
-
end
|
203
|
-
|
204
|
-
state_machine :initial => :idle do
|
203
|
+
state_machine initial: :idle do
|
205
204
|
extend StateMachineJob::Macro
|
206
205
|
|
207
206
|
state :idle
|
@@ -210,13 +209,13 @@ module StateMachineJob
|
|
210
209
|
state :other
|
211
210
|
|
212
211
|
event :run do
|
213
|
-
transition :
|
212
|
+
transition idle: :running
|
214
213
|
end
|
215
214
|
|
216
|
-
job TestJob
|
215
|
+
job TestJob do
|
217
216
|
on_enter :running
|
218
|
-
result :ok, :
|
219
|
-
result :ok, :
|
217
|
+
result :ok, state: :done, if: -> { true }
|
218
|
+
result :ok, state: :other
|
220
219
|
end
|
221
220
|
end
|
222
221
|
end.new
|
@@ -230,12 +229,12 @@ module StateMachineJob
|
|
230
229
|
it 'raises descriptive error when used in combination with :retry_after option' do
|
231
230
|
expect {
|
232
231
|
Class.new do
|
233
|
-
state_machine :
|
232
|
+
state_machine initial: :idle do
|
234
233
|
extend StateMachineJob::Macro
|
235
234
|
|
236
235
|
job TestJob do
|
237
236
|
on_enter :running
|
238
|
-
result :ok, :
|
237
|
+
result :ok, state: :done, if: true, retry_after: 100
|
239
238
|
end
|
240
239
|
end
|
241
240
|
end
|
@@ -244,34 +243,31 @@ module StateMachineJob
|
|
244
243
|
end
|
245
244
|
|
246
245
|
describe ':retry_if_state option' do
|
247
|
-
|
248
|
-
|
249
|
-
object = Class.new do
|
250
|
-
def id
|
251
|
-
43
|
252
|
-
end
|
246
|
+
class ModelWithRetryIfState < BaseModel
|
247
|
+
attr_accessor :state, :some_attribute
|
253
248
|
|
254
|
-
|
255
|
-
|
249
|
+
state_machine initial: :idle do
|
250
|
+
extend StateMachineJob::Macro
|
256
251
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
252
|
+
state :idle
|
253
|
+
state :running
|
254
|
+
state :done
|
255
|
+
state :failed
|
261
256
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
257
|
+
event :run do
|
258
|
+
transition idle: :running
|
259
|
+
transition running: :rerun_required
|
260
|
+
end
|
266
261
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
end
|
262
|
+
job TestJob do
|
263
|
+
on_enter :running
|
264
|
+
result :ok, state: :done, retry_if_state: :rerun_required
|
271
265
|
end
|
272
|
-
end
|
266
|
+
end
|
267
|
+
end
|
273
268
|
|
274
|
-
|
269
|
+
it 'returns to on_enter state if state matches option when job finishes' do
|
270
|
+
object = ModelWithRetryIfState.new(id: 43)
|
275
271
|
|
276
272
|
object.state = :running
|
277
273
|
object.run
|
@@ -281,31 +277,7 @@ module StateMachineJob
|
|
281
277
|
end
|
282
278
|
|
283
279
|
it 'returns to result state if state does not match option when job finishes' do
|
284
|
-
|
285
|
-
object = Class.new do
|
286
|
-
def id
|
287
|
-
43
|
288
|
-
end
|
289
|
-
|
290
|
-
state_machine :initial => :idle do
|
291
|
-
extend StateMachineJob::Macro
|
292
|
-
|
293
|
-
state :idle
|
294
|
-
state :running
|
295
|
-
state :done
|
296
|
-
state :failed
|
297
|
-
|
298
|
-
event :run do
|
299
|
-
transition :idle => :running
|
300
|
-
transition :running => :rerun_required
|
301
|
-
end
|
302
|
-
|
303
|
-
job TestJob, queue do
|
304
|
-
on_enter :running
|
305
|
-
result :ok, :state => :done, :retry_if_state => :rerun_required
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end.new
|
280
|
+
object = ModelWithRetryIfState.new(id: 43)
|
309
281
|
|
310
282
|
object.state = :running
|
311
283
|
object.state_machine_job_test_job_ok
|
@@ -316,11 +288,11 @@ module StateMachineJob
|
|
316
288
|
it 'raises descriptive error when on_enter is used after result' do
|
317
289
|
expect {
|
318
290
|
Class.new do
|
319
|
-
state_machine :
|
291
|
+
state_machine initial: :idle do
|
320
292
|
extend StateMachineJob::Macro
|
321
293
|
|
322
294
|
job TestJob do
|
323
|
-
result :ok, :
|
295
|
+
result :ok, state: :done, retry_if_state: :rerun_required
|
324
296
|
on_enter :running
|
325
297
|
end
|
326
298
|
end
|
@@ -331,12 +303,12 @@ module StateMachineJob
|
|
331
303
|
it 'raises descriptive error when used in combination with :retry_after option' do
|
332
304
|
expect {
|
333
305
|
Class.new do
|
334
|
-
state_machine :
|
306
|
+
state_machine initial: :idle do
|
335
307
|
extend StateMachineJob::Macro
|
336
308
|
|
337
309
|
job TestJob do
|
338
310
|
on_enter :running
|
339
|
-
result :ok, :
|
311
|
+
result :ok, state: :done, retry_if_state: :rerun_required, retry_after: 100
|
340
312
|
end
|
341
313
|
end
|
342
314
|
end
|
@@ -347,11 +319,11 @@ module StateMachineJob
|
|
347
319
|
it 'does not raise exception if on_enter is used after result without :retry_if_state option' do
|
348
320
|
expect {
|
349
321
|
Class.new do
|
350
|
-
state_machine :
|
322
|
+
state_machine initial: :idle do
|
351
323
|
extend StateMachineJob::Macro
|
352
324
|
|
353
325
|
job TestJob do
|
354
|
-
result :ok, :
|
326
|
+
result :ok, state: :done
|
355
327
|
on_enter :running
|
356
328
|
end
|
357
329
|
end
|
@@ -1,118 +1,64 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe StateMachineJob do
|
4
|
-
class
|
5
|
-
|
6
|
-
job.perform(*args)
|
7
|
-
end
|
4
|
+
class TestJob < ActiveJob::Base
|
5
|
+
include StateMachineJob
|
8
6
|
|
9
|
-
def
|
10
|
-
@instance ||= TestQueue.new
|
11
|
-
end
|
7
|
+
def perform_with_result(record, payload); end
|
12
8
|
end
|
13
9
|
|
14
|
-
class
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
class Model
|
11
|
+
def id
|
12
|
+
3
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_job_ok!; end
|
18
16
|
|
19
|
-
|
20
|
-
@queue = 'test_job_2'
|
21
|
-
extend StateMachineJob
|
17
|
+
def test_job_error!; end
|
22
18
|
end
|
23
19
|
|
24
20
|
class SomeError < StandardError; end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
state :idle
|
31
|
-
state :first_running
|
32
|
-
state :second_running
|
33
|
-
state :done
|
34
|
-
state :failed
|
35
|
-
|
36
|
-
event :run do
|
37
|
-
transition :idle => :first_running
|
38
|
-
end
|
39
|
-
|
40
|
-
job TestJob1, TestQueue.instance do
|
41
|
-
on_enter :first_running
|
42
|
-
payload do |object|
|
43
|
-
{:n => 1}
|
44
|
-
end
|
45
|
-
result :ok => :second_running
|
46
|
-
result :error => :failed
|
47
|
-
end
|
48
|
-
|
49
|
-
job TestJob2, TestQueue.instance do
|
50
|
-
on_enter :second_running
|
51
|
-
payload do |object|
|
52
|
-
{:n => 2}
|
53
|
-
end
|
54
|
-
result :ok => :done
|
55
|
-
result :error => :failed
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'calls find on model and passes record and payload to perform_with_result method' do
|
61
|
-
model = Model.new
|
22
|
+
it 'passes record and payload to perform_with_result method' do
|
23
|
+
record = Model.new
|
24
|
+
payload = {n: 1}
|
25
|
+
job = TestJob.new
|
62
26
|
|
63
|
-
|
64
|
-
|
65
|
-
expect(TestJob1).to receive(:perform_with_result).with(model, {:n => 1}).and_return(:ok)
|
66
|
-
expect(TestJob2).to receive(:perform_with_result).with(model, {:n => 2}).and_return(:ok)
|
27
|
+
expect(job).to receive(:perform_with_result)
|
28
|
+
.with(record, payload).and_return(:ok)
|
67
29
|
|
68
|
-
|
30
|
+
job.perform(record, payload)
|
69
31
|
end
|
70
32
|
|
71
33
|
it 'invokes job result event on record' do
|
72
|
-
|
34
|
+
record = Model.new
|
35
|
+
job = TestJob.new
|
73
36
|
|
74
|
-
allow(
|
75
|
-
|
76
|
-
allow(TestJob1).to receive(:perform_with_result).and_return(:ok)
|
77
|
-
allow(TestJob2).to receive(:perform_with_result).and_return(:ok)
|
37
|
+
allow(job).to receive(:perform_with_result).and_return(:ok)
|
38
|
+
expect(record).to receive(:test_job_ok!)
|
78
39
|
|
79
|
-
|
80
|
-
|
81
|
-
model.run
|
40
|
+
job.perform(record)
|
82
41
|
end
|
83
42
|
|
84
43
|
it 'lets exception bubble raised by perform_with_result' do
|
85
|
-
|
44
|
+
record = Model.new
|
45
|
+
job = TestJob.new
|
86
46
|
|
87
|
-
allow(
|
88
|
-
allow(Model).to receive(:find_by_id).and_return(model)
|
89
|
-
allow(TestJob1).to receive(:perform_with_result).and_raise(SomeError)
|
47
|
+
allow(job).to receive(:perform_with_result).and_raise(SomeError)
|
90
48
|
|
91
|
-
expect {
|
92
|
-
model.run
|
93
|
-
}.to raise_error(SomeError)
|
49
|
+
expect { job.perform(record) }.to raise_error(SomeError)
|
94
50
|
end
|
95
51
|
|
96
52
|
it 'invokes error job result event on record if perform_with_result raises' do
|
97
|
-
|
98
|
-
|
99
|
-
allow(model).to receive(:id).and_return(5)
|
100
|
-
allow(Model).to receive(:find_by_id).and_return(model)
|
101
|
-
allow(TestJob1).to receive(:perform_with_result).and_raise(SomeError)
|
53
|
+
record = Model.new
|
54
|
+
job = TestJob.new
|
102
55
|
|
103
|
-
|
56
|
+
allow(job).to receive(:perform_with_result).and_raise(SomeError)
|
57
|
+
expect(record).to receive(:test_job_error!)
|
104
58
|
|
105
59
|
begin
|
106
|
-
|
107
|
-
rescue SomeError
|
60
|
+
job.perform(record)
|
61
|
+
rescue SomeError # rubocop:disable Lint/HandleExceptions
|
108
62
|
end
|
109
63
|
end
|
110
|
-
|
111
|
-
it 'job is skipped if record cannot be found' do
|
112
|
-
allow(Model).to receive(:find_by_id).and_return(nil)
|
113
|
-
|
114
|
-
expect {
|
115
|
-
TestJob1.perform(Model.name, -1, {})
|
116
|
-
}.not_to raise_exception
|
117
|
-
end
|
118
64
|
end
|
data/state_machine_job.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = StateMachineJob::VERSION
|
9
9
|
spec.authors = ["Codevise Solutions Ltd."]
|
10
10
|
spec.email = ["info@codevise.de"]
|
11
|
-
spec.description = %q{State Machine +
|
12
|
-
spec.summary = %q{
|
11
|
+
spec.description = %q{State Machine + Active Job}
|
12
|
+
spec.summary = %q{Trigger jobs via Rails state machines.}
|
13
13
|
spec.homepage = "http://github.com/codevise/state_machine_job"
|
14
14
|
spec.licenses = ['MIT']
|
15
15
|
|
@@ -20,11 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
22
|
spec.add_development_dependency 'rake', '< 13'
|
23
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
24
|
-
spec.add_development_dependency 'activesupport', '<
|
23
|
+
spec.add_development_dependency 'rspec-rails', '~> 3.7'
|
24
|
+
spec.add_development_dependency 'activesupport', '< 6'
|
25
|
+
spec.add_development_dependency 'activemodel', '< 6'
|
25
26
|
spec.add_development_dependency 'semmy', '~> 1.0'
|
27
|
+
spec.add_development_dependency 'timecop', '~> 0.9.1'
|
26
28
|
|
27
|
-
spec.add_runtime_dependency '
|
28
|
-
spec.add_runtime_dependency 'resque-logger', '~> 0.2.0'
|
29
|
+
spec.add_runtime_dependency 'activejob', ['>= 4.2', '< 6']
|
29
30
|
spec.add_runtime_dependency 'state_machine', '~> 1.2'
|
30
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machine_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Codevise Solutions Ltd.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,33 +39,47 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '13'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
42
|
+
name: rspec-rails
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.7'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
54
|
+
version: '3.7'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: activesupport
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "<"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '6'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "<"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activemodel
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "<"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '6'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: semmy
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,33 +95,39 @@ dependencies:
|
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '1.0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: timecop
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
90
|
-
type: :
|
103
|
+
version: 0.9.1
|
104
|
+
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
110
|
+
version: 0.9.1
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: activejob
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
117
|
+
version: '4.2'
|
118
|
+
- - "<"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '6'
|
104
121
|
type: :runtime
|
105
122
|
prerelease: false
|
106
123
|
version_requirements: !ruby/object:Gem::Requirement
|
107
124
|
requirements:
|
108
|
-
- - "
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '4.2'
|
128
|
+
- - "<"
|
109
129
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
130
|
+
version: '6'
|
111
131
|
- !ruby/object:Gem::Dependency
|
112
132
|
name: state_machine
|
113
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,7 +142,7 @@ dependencies:
|
|
122
142
|
- - "~>"
|
123
143
|
- !ruby/object:Gem::Version
|
124
144
|
version: '1.2'
|
125
|
-
description: State Machine +
|
145
|
+
description: State Machine + Active Job
|
126
146
|
email:
|
127
147
|
- info@codevise.de
|
128
148
|
executables: []
|
@@ -142,7 +162,6 @@ files:
|
|
142
162
|
- spec/spec_helper.rb
|
143
163
|
- spec/state_machine_job/macro_spec.rb
|
144
164
|
- spec/state_machine_job_spec.rb
|
145
|
-
- spec/support/setup_resque_logger.rb
|
146
165
|
- state_machine_job.gemspec
|
147
166
|
homepage: http://github.com/codevise/state_machine_job
|
148
167
|
licenses:
|
@@ -164,12 +183,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
183
|
version: '0'
|
165
184
|
requirements: []
|
166
185
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.7.5
|
168
187
|
signing_key:
|
169
188
|
specification_version: 4
|
170
|
-
summary:
|
189
|
+
summary: Trigger jobs via Rails state machines.
|
171
190
|
test_files:
|
172
191
|
- spec/spec_helper.rb
|
173
192
|
- spec/state_machine_job/macro_spec.rb
|
174
193
|
- spec/state_machine_job_spec.rb
|
175
|
-
- spec/support/setup_resque_logger.rb
|