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 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 leaves of the tree
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
- * `{ async: true }` if you need your process to wait for an outsider to continue.
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
- node.instance_eval(&block) if block_given?
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
- unless perform.kind_of? Proc
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
 
@@ -12,7 +12,7 @@ class ResqueJobsTree::Definitions::Tree < ResqueJobsTree::Definitions
12
12
 
13
13
  def root name=nil, &block
14
14
  @root ||= Node.new(name, self).tap do |root|
15
- root.instance_eval &block
15
+ root.instance_eval &block if block_given?
16
16
  end
17
17
  end
18
18
 
@@ -1,5 +1,4 @@
1
1
  module ResqueJobsTree::Factory
2
-
3
2
  extend self
4
3
 
5
4
  def create name, &block
@@ -70,14 +70,14 @@ class ResqueJobsTree::Node
70
70
  @childs = definition.leaf? ? [] : definition.childs.call(*resources)
71
71
  end
72
72
 
73
- def launch
73
+ def register
74
74
  store unless root?
75
75
  if leaf?
76
- tree.register_a_leaf self
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.launch
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, :leaves
5
+ attr_reader :definition, :resources, :nodes
6
6
 
7
7
  def initialize definition, resources
8
8
  @definition = definition
9
9
  @resources = resources
10
- @leaves = []
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.launch
22
- enqueue_leaves_jobs
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 register_a_leaf node
41
- @leaves << node
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 enqueue_leaves_jobs
56
- @leaves.each do |leaf|
57
- leaf.enqueue unless leaf.definition.options[:async]
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
 
@@ -1,3 +1,3 @@
1
1
  module ResqueJobsTree
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -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 = "resque_jobs_tree"
7
+ spec.name = 'resque_jobs_tree'
8
8
  spec.version = ResqueJobsTree::VERSION
9
- spec.authors = ["Antoine Qu'hen"]
10
- spec.email = ["antoinequhen@gmail.com"]
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 = "MIT"
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 = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
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
@@ -91,7 +91,7 @@ class DefinitionsTest < MiniTest::Unit::TestCase
91
91
  end
92
92
 
93
93
  def test_options
94
- options = { async: true }
94
+ options = { triggerable: true }
95
95
  @leaf.options = options
96
96
  assert_equal options, @tree.find(:node2).options
97
97
  end
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).launch
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 test_launch_async
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, async: true do
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 test_nested_tree
173
+ def test_nested_tree_with_job_failure
144
174
  Resque.inline = false
145
- create_nested_tree
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 test_async_tree
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, async: true do
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 test_async_tree_with_fail
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, async: true do
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 create_nested_tree
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, async: true do
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 test_leaves
14
- assert_equal @tree_definition.spawn([]).leaves, []
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 test_register_a_leaf
21
+ def test_register_node
22
22
  leaf = 'leaf'
23
23
  tree = @tree_definition.spawn []
24
- tree.register_a_leaf leaf
25
- assert_equal tree.leaves, [leaf]
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 = create_nested_tree
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.3
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-25 00:00:00.000000000 Z
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