resque_jobs_tree 0.4.3 → 0.5.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.
- data/README.md +2 -2
- data/lib/resque_jobs_tree/definitions/node.rb +26 -2
- data/lib/resque_jobs_tree/definitions/tree.rb +1 -1
- data/lib/resque_jobs_tree/factory.rb +0 -1
- data/lib/resque_jobs_tree/node.rb +4 -4
- data/lib/resque_jobs_tree/tree.rb +12 -9
- data/lib/resque_jobs_tree/version.rb +1 -1
- data/resque_jobs_tree.gemspec +9 -8
- data/test/definitions_test.rb +1 -1
- data/test/factory_test.rb +30 -0
- data/test/process_test.rb +39 -9
- data/test/test_helper.rb +2 -2
- data/test/tree_test.rb +6 -6
- metadata +18 -2
data/README.md
CHANGED
@@ -52,7 +52,7 @@ Organise each sequences of jobs into a single file
|
|
52
52
|
This code is defining the tree, then when it launches the sequence of jobs, it:
|
53
53
|
* stocks in Redis all the Resque jobs which needs to be done including the needed parameters to run them.
|
54
54
|
* stocks in Redis the childhood relationsips between them.
|
55
|
-
* enqueues in Resque the jobs which are the
|
55
|
+
* enqueues in Resque the jobs which are the nodes of the tree
|
56
56
|
|
57
57
|
Limitations:
|
58
58
|
|
@@ -64,7 +64,7 @@ you can't enqueue 2 times `[:mail, User.first]`
|
|
64
64
|
|
65
65
|
Node options:
|
66
66
|
|
67
|
-
* `{
|
67
|
+
* `{ triggerable: true }` if you need your process to wait for an outsider to start.
|
68
68
|
* `{ continue_on_fail: true}` if your process can continue even after a fail during a job.
|
69
69
|
|
70
70
|
## Contributing
|
@@ -14,7 +14,11 @@ class ResqueJobsTree::Definitions::Node < ResqueJobsTree::Definitions
|
|
14
14
|
ResqueJobsTree::Definitions::Node.new(name, tree, self).tap do |node|
|
15
15
|
node.options = options
|
16
16
|
@node_childs << node
|
17
|
-
|
17
|
+
if block_given?
|
18
|
+
node.instance_eval &block
|
19
|
+
elsif options.has_key? :triggerable
|
20
|
+
node.perform {}
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
@@ -49,18 +53,38 @@ class ResqueJobsTree::Definitions::Node < ResqueJobsTree::Definitions
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def validate!
|
56
|
+
# Should have a child's naming [:job1, ...] and node childs Proc implementation associated
|
57
|
+
# node :job1 do
|
58
|
+
# perform {}
|
59
|
+
# end
|
60
|
+
# ...
|
52
61
|
if (childs.kind_of?(Proc) && node_childs.empty?) || (childs.nil? && !node_childs.empty?)
|
53
62
|
raise ResqueJobsTree::NodeDefinitionInvalid,
|
54
63
|
"node `#{name}` from tree `#{tree.name}` should defines childs and child nodes"
|
55
64
|
end
|
56
|
-
|
65
|
+
|
66
|
+
# Should have an implementation
|
67
|
+
# node :job1 do
|
68
|
+
# perform {}
|
69
|
+
# end
|
70
|
+
if !perform.kind_of? Proc and !options.has_key? :triggerable
|
57
71
|
raise ResqueJobsTree::NodeDefinitionInvalid,
|
58
72
|
"node `#{name}` from tree `#{tree.name}` has no perform block"
|
59
73
|
end
|
74
|
+
|
75
|
+
# Naming Should be uniq
|
60
76
|
if (tree.nodes - [self]).map(&:name).include? name
|
61
77
|
raise ResqueJobsTree::NodeDefinitionInvalid,
|
62
78
|
"node name `#{name}` is already taken in tree `#{tree.name}`"
|
63
79
|
end
|
80
|
+
|
81
|
+
# Only one job can be trigger tree
|
82
|
+
if node_childs.select { |entry| entry.options.has_key?(:triggerable) }.size > 1
|
83
|
+
raise ResqueJobsTree::NodeDefinitionInvalid,
|
84
|
+
"Only one job must be declared to be triggerable into an definition, tree `#{tree.name}`"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Recursive call for validate all of tree
|
64
88
|
node_childs.each &:validate!
|
65
89
|
end
|
66
90
|
|
@@ -70,14 +70,14 @@ class ResqueJobsTree::Node
|
|
70
70
|
@childs = definition.leaf? ? [] : definition.childs.call(*resources)
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
73
|
+
def register
|
74
74
|
store unless root?
|
75
75
|
if leaf?
|
76
|
-
tree.
|
76
|
+
tree.register_node self
|
77
77
|
else
|
78
78
|
childs.each do |node_name, *resources|
|
79
79
|
node = definition.find(node_name).spawn resources, self
|
80
|
-
node.
|
80
|
+
node.register
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -96,7 +96,7 @@ class ResqueJobsTree::Node
|
|
96
96
|
puts "[ResqueJobsTree::Tree] after_perform callback of node #{definition.tree.name}##{name} has failed."\
|
97
97
|
" Continuing for cleanup."
|
98
98
|
else
|
99
|
-
raise
|
99
|
+
raise
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -2,12 +2,12 @@ class ResqueJobsTree::Tree
|
|
2
2
|
|
3
3
|
include ResqueJobsTree::Storage::Tree
|
4
4
|
|
5
|
-
attr_reader :definition, :resources, :
|
5
|
+
attr_reader :definition, :resources, :nodes
|
6
6
|
|
7
7
|
def initialize definition, resources
|
8
8
|
@definition = definition
|
9
9
|
@resources = resources
|
10
|
-
@
|
10
|
+
@nodes = []
|
11
11
|
end
|
12
12
|
|
13
13
|
def name
|
@@ -18,8 +18,11 @@ class ResqueJobsTree::Tree
|
|
18
18
|
if uniq?
|
19
19
|
before_perform
|
20
20
|
store
|
21
|
-
root.
|
22
|
-
|
21
|
+
root.register
|
22
|
+
enqueue_jobs
|
23
|
+
else
|
24
|
+
raise ResqueJobsTree::JobNotUniq,
|
25
|
+
"Tree Definition must be uniq"
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -37,8 +40,8 @@ class ResqueJobsTree::Tree
|
|
37
40
|
@root ||= ResqueJobsTree::Node.new(definition.root, resources, nil, self)
|
38
41
|
end
|
39
42
|
|
40
|
-
def
|
41
|
-
@
|
43
|
+
def register_node node
|
44
|
+
@nodes << node
|
42
45
|
end
|
43
46
|
|
44
47
|
def inspect
|
@@ -52,9 +55,9 @@ class ResqueJobsTree::Tree
|
|
52
55
|
|
53
56
|
private
|
54
57
|
|
55
|
-
def
|
56
|
-
@
|
57
|
-
leaf.enqueue unless leaf.definition.options[:
|
58
|
+
def enqueue_jobs
|
59
|
+
@nodes.each do |leaf|
|
60
|
+
leaf.enqueue unless leaf.definition.options[:triggerable]
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
data/resque_jobs_tree.gemspec
CHANGED
@@ -4,23 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'resque_jobs_tree/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'resque_jobs_tree'
|
8
8
|
spec.version = ResqueJobsTree::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Antoine Qu\'hen']
|
10
|
+
spec.email = ['antoinequhen@gmail.com']
|
11
11
|
spec.description = %q{To manage complexe background job processes, this gem simplify the task of creating sequences of Resque jobs by putting them into a tree.}
|
12
12
|
spec.summary = %q{Organise Resque jobs as a tree.}
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
23
|
spec.add_development_dependency 'minitest'
|
24
24
|
spec.add_development_dependency 'mock_redis'
|
25
|
+
spec.add_development_dependency 'mocha'
|
25
26
|
spec.add_dependency 'resque', '~> 1.24'
|
26
27
|
end
|
data/test/definitions_test.rb
CHANGED
data/test/factory_test.rb
CHANGED
@@ -14,4 +14,34 @@ class FactoryTest < MiniTest::Unit::TestCase
|
|
14
14
|
assert_equal ResqueJobsTree::Factory.find(@tree_definition.name).name, @tree_definition.name
|
15
15
|
end
|
16
16
|
|
17
|
+
def test_without_perform_whitout_flag
|
18
|
+
assert_raises ResqueJobsTree::NodeDefinitionInvalid do
|
19
|
+
ResqueJobsTree::Factory.create :tree_with_job_without_perform do
|
20
|
+
root :job_without_perform
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_without_perform
|
26
|
+
assert_not_raises do
|
27
|
+
ResqueJobsTree::Factory.create :tree_with_job_without_perform do
|
28
|
+
# root :job_without_perform, triggerable: true
|
29
|
+
root :job_without_perform do
|
30
|
+
perform { puts 'job1' }
|
31
|
+
childs { [:job1] }
|
32
|
+
node :job1 , triggerable: true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end.must_equal 'ok'
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_not_raises
|
39
|
+
begin
|
40
|
+
yield
|
41
|
+
'ok'
|
42
|
+
rescue
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
17
47
|
end
|
data/test/process_test.rb
CHANGED
@@ -2,10 +2,23 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ProcessTest < MiniTest::Unit::TestCase
|
4
4
|
|
5
|
+
def test_launch_without_uniq
|
6
|
+
create_tree
|
7
|
+
assert_raises ResqueJobsTree::JobNotUniq do
|
8
|
+
resque_jobs_tree = @tree_definition.spawn [1, 2, 3]
|
9
|
+
resque_jobs_tree.stub :uniq?, false do
|
10
|
+
resque_jobs_tree.launch
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
def test_launch
|
6
16
|
create_tree
|
7
17
|
resources = [1, 2, 3]
|
8
|
-
@tree_definition.spawn(resources)
|
18
|
+
resque_jobs_tree = @tree_definition.spawn(resources)
|
19
|
+
resque_jobs_tree.stub :uniq?, true do
|
20
|
+
resque_jobs_tree.launch
|
21
|
+
end
|
9
22
|
history = ['tree1 job2']*3+['tree1 job1']
|
10
23
|
assert_equal history, redis.lrange('history', 0, -1)
|
11
24
|
end
|
@@ -31,12 +44,29 @@ class ProcessTest < MiniTest::Unit::TestCase
|
|
31
44
|
assert_redis_empty
|
32
45
|
end
|
33
46
|
|
34
|
-
def
|
47
|
+
def test_just_one_triggerable_job
|
48
|
+
assert_raises ResqueJobsTree::NodeDefinitionInvalid do
|
49
|
+
tree_definition = ResqueJobsTree::Factory.create :tree1 do
|
50
|
+
root :job1 do
|
51
|
+
perform { puts 'job1' }
|
52
|
+
childs { [:job2, :job3] }
|
53
|
+
node :job2, triggerable: true do
|
54
|
+
perform {}
|
55
|
+
end
|
56
|
+
node :job3, triggerable: true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
tree = tree_definition.spawn [1, 2, 3]
|
60
|
+
tree.launch
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_launch_triggerable
|
35
65
|
tree_definition = ResqueJobsTree::Factory.create :tree1 do
|
36
66
|
root :job1 do
|
37
67
|
perform { raise 'should not arrive here' }
|
38
68
|
childs { [:job2] }
|
39
|
-
node :job2,
|
69
|
+
node :job2, triggerable: true do
|
40
70
|
perform {}
|
41
71
|
end
|
42
72
|
end
|
@@ -140,9 +170,9 @@ class ProcessTest < MiniTest::Unit::TestCase
|
|
140
170
|
ResqueJobsTree.launch tree_definition.name, Model.new(1), 1
|
141
171
|
end
|
142
172
|
|
143
|
-
def
|
173
|
+
def test_nested_tree_with_job_failure
|
144
174
|
Resque.inline = false
|
145
|
-
|
175
|
+
create_nested_tree_with_job_failure
|
146
176
|
@tree_definition.spawn([1,2,3]).launch
|
147
177
|
assert_raises RuntimeError do # job4 error
|
148
178
|
run_resque_workers @tree_definition.name
|
@@ -157,12 +187,12 @@ class ProcessTest < MiniTest::Unit::TestCase
|
|
157
187
|
end
|
158
188
|
end
|
159
189
|
|
160
|
-
def
|
190
|
+
def test_triggerable_tree
|
161
191
|
tree_definition = ResqueJobsTree::Factory.create :tree1 do
|
162
192
|
root :job1 do
|
163
193
|
perform { raise 'should not arrive here' }
|
164
194
|
childs { [ [:job2], [:job3] ] }
|
165
|
-
node :job2,
|
195
|
+
node :job2, triggerable: true do
|
166
196
|
perform {}
|
167
197
|
end
|
168
198
|
node :job3 do
|
@@ -177,13 +207,13 @@ class ProcessTest < MiniTest::Unit::TestCase
|
|
177
207
|
assert_equal parents_hash, Resque.redis.hgetall(ResqueJobsTree::Storage::PARENTS_KEY)
|
178
208
|
end
|
179
209
|
|
180
|
-
def
|
210
|
+
def test_triggerable_tree_with_fail
|
181
211
|
Resque.inline = false
|
182
212
|
tree_definition = ResqueJobsTree::Factory.create :tree1 do
|
183
213
|
root :job1 do
|
184
214
|
perform { raise 'should not arrive here' }
|
185
215
|
childs { [ [:job2], [:job3] ] }
|
186
|
-
node :job2,
|
216
|
+
node :job2, triggerable: true do
|
187
217
|
perform {}
|
188
218
|
end
|
189
219
|
node :job3, continue_on_failure: true do
|
data/test/test_helper.rb
CHANGED
@@ -70,7 +70,7 @@ class MiniTest::Unit::TestCase
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
73
|
+
def create_nested_tree_with_job_failure
|
74
74
|
@tree_definition = ResqueJobsTree::Factory.create :tree1 do
|
75
75
|
root :job1 do
|
76
76
|
perform { raise ExpectedException, 'job1' }
|
@@ -78,7 +78,7 @@ class MiniTest::Unit::TestCase
|
|
78
78
|
node :job2, continue_on_failure: true do
|
79
79
|
perform { raise 'job2' }
|
80
80
|
childs { [ [:job3], [:job4] ] }
|
81
|
-
node :job3,
|
81
|
+
node :job3, triggerable: true do
|
82
82
|
perform {}
|
83
83
|
end
|
84
84
|
node :job4, continue_on_failure: true do
|
data/test/tree_test.rb
CHANGED
@@ -10,24 +10,24 @@ class TreeTest < MiniTest::Unit::TestCase
|
|
10
10
|
assert_equal @tree_definition.name, 'tree1'
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
assert_equal @tree_definition.spawn([]).
|
13
|
+
def test_nodes
|
14
|
+
assert_equal @tree_definition.spawn([]).nodes, []
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_root
|
18
18
|
assert @tree_definition.root.kind_of? ResqueJobsTree::Definitions::Node
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def test_register_node
|
22
22
|
leaf = 'leaf'
|
23
23
|
tree = @tree_definition.spawn []
|
24
|
-
tree.
|
25
|
-
assert_equal tree.
|
24
|
+
tree.register_node leaf
|
25
|
+
assert_equal tree.nodes, [leaf]
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_find
|
29
29
|
assert_equal 'job2', @tree_definition.find(:job2).name
|
30
|
-
tree_definition =
|
30
|
+
tree_definition = create_nested_tree_with_job_failure
|
31
31
|
assert_equal 'job4', tree_definition.find(:job4).name
|
32
32
|
end
|
33
33
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque_jobs_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -75,6 +75,22 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mocha
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
78
94
|
- !ruby/object:Gem::Dependency
|
79
95
|
name: resque
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|