state_machine_job 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/state_machine_job.svg)](http://badge.fury.io/rb/state_machine_job)
|
4
4
|
[![Build Status](https://travis-ci.org/codevise/state_machine_job.svg?branch=master)](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
|