resque-mongo 1.4.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CONTRIBUTORS +24 -6
  2. data/HISTORY.md +65 -0
  3. data/README.markdown +34 -5
  4. data/Rakefile +1 -1
  5. data/bin/resque +2 -2
  6. data/bin/resque-web +6 -1
  7. data/deps.rip +2 -2
  8. data/docs/HOOKS.md +121 -0
  9. data/docs/PLUGINS.md +93 -0
  10. data/examples/demo/Rakefile +5 -0
  11. data/examples/monit/resque.monit +6 -0
  12. data/lib/resque.rb +94 -7
  13. data/lib/resque/errors.rb +3 -0
  14. data/lib/resque/failure.rb +3 -0
  15. data/lib/resque/failure/base.rb +3 -0
  16. data/lib/resque/failure/hoptoad.rb +29 -19
  17. data/lib/resque/failure/mongo.rb +10 -1
  18. data/lib/resque/helpers.rb +8 -2
  19. data/lib/resque/job.rb +107 -2
  20. data/lib/resque/plugin.rb +46 -0
  21. data/lib/resque/server.rb +30 -11
  22. data/lib/resque/server/public/ranger.js +50 -7
  23. data/lib/resque/server/public/style.css +8 -1
  24. data/lib/resque/server/test_helper.rb +19 -0
  25. data/lib/resque/server/views/failed.erb +17 -3
  26. data/lib/resque/server/views/key_sets.erb +20 -0
  27. data/lib/resque/server/views/{key.erb → key_string.erb} +2 -8
  28. data/lib/resque/server/views/queues.erb +5 -2
  29. data/lib/resque/server/views/stats.erb +2 -2
  30. data/lib/resque/server/views/workers.erb +1 -1
  31. data/lib/resque/server/views/working.erb +2 -0
  32. data/lib/resque/tasks.rb +1 -1
  33. data/lib/resque/version.rb +1 -1
  34. data/lib/resque/worker.rb +54 -15
  35. data/tasks/redis.rake +53 -29
  36. data/test/job_hooks_test.rb +302 -0
  37. data/test/job_plugins_test.rb +209 -0
  38. data/test/plugin_test.rb +116 -0
  39. data/test/resque-mongo_benchmark.rb +62 -0
  40. data/test/resque-web_test.rb +54 -0
  41. data/test/resque_test.rb +34 -0
  42. data/test/test_helper.rb +15 -0
  43. data/test/worker_test.rb +62 -2
  44. metadata +58 -23
@@ -0,0 +1,209 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Multiple plugins with multiple hooks" do
4
+ include PerformJob
5
+
6
+ module Plugin1
7
+ def before_perform_record_history1(history)
8
+ history << :before1
9
+ end
10
+ def after_perform_record_history1(history)
11
+ history << :after1
12
+ end
13
+ end
14
+
15
+ module Plugin2
16
+ def before_perform_record_history2(history)
17
+ history << :before2
18
+ end
19
+ def after_perform_record_history2(history)
20
+ history << :after2
21
+ end
22
+ end
23
+
24
+ class ManyBeforesJob
25
+ extend Plugin1
26
+ extend Plugin2
27
+ def self.perform(history)
28
+ history << :perform
29
+ end
30
+ end
31
+
32
+ test "hooks of each type are executed in alphabetical order" do
33
+ result = perform_job(ManyBeforesJob, history=[])
34
+ assert_equal true, result, "perform returned true"
35
+ assert_equal [:before1, :before2, :perform, :after1, :after2], history
36
+ end
37
+ end
38
+
39
+ context "Resque::Plugin ordering before_perform" do
40
+ include PerformJob
41
+
42
+ module BeforePerformPlugin
43
+ def before_perform1(history)
44
+ history << :before_perform1
45
+ end
46
+ end
47
+
48
+ class BeforePerformJob
49
+ extend BeforePerformPlugin
50
+ def self.perform(history)
51
+ history << :perform
52
+ end
53
+ def self.before_perform(history)
54
+ history << :before_perform
55
+ end
56
+ end
57
+
58
+ test "before_perform hooks are executed in order" do
59
+ result = perform_job(BeforePerformJob, history=[])
60
+ assert_equal true, result, "perform returned true"
61
+ assert_equal [:before_perform, :before_perform1, :perform], history
62
+ end
63
+ end
64
+
65
+ context "Resque::Plugin ordering after_perform" do
66
+ include PerformJob
67
+
68
+ module AfterPerformPlugin
69
+ def after_perform_record_history(history)
70
+ history << :after_perform1
71
+ end
72
+ end
73
+
74
+ class AfterPerformJob
75
+ extend AfterPerformPlugin
76
+ def self.perform(history)
77
+ history << :perform
78
+ end
79
+ def self.after_perform(history)
80
+ history << :after_perform
81
+ end
82
+ end
83
+
84
+ test "after_perform hooks are executed in order" do
85
+ result = perform_job(AfterPerformJob, history=[])
86
+ assert_equal true, result, "perform returned true"
87
+ assert_equal [:perform, :after_perform, :after_perform1], history
88
+ end
89
+ end
90
+
91
+ context "Resque::Plugin ordering around_perform" do
92
+ include PerformJob
93
+
94
+ module AroundPerformPlugin1
95
+ def around_perform1(history)
96
+ history << :around_perform_plugin1
97
+ yield
98
+ end
99
+ end
100
+
101
+ class AroundPerformJustPerformsJob
102
+ extend AroundPerformPlugin1
103
+ def self.perform(history)
104
+ history << :perform
105
+ end
106
+ end
107
+
108
+ test "around_perform hooks are executed before the job" do
109
+ result = perform_job(AroundPerformJustPerformsJob, history=[])
110
+ assert_equal true, result, "perform returned true"
111
+ assert_equal [:around_perform_plugin1, :perform], history
112
+ end
113
+
114
+ class AroundPerformJob
115
+ extend AroundPerformPlugin1
116
+ def self.perform(history)
117
+ history << :perform
118
+ end
119
+ def self.around_perform(history)
120
+ history << :around_perform
121
+ yield
122
+ end
123
+ end
124
+
125
+ test "around_perform hooks are executed in order" do
126
+ result = perform_job(AroundPerformJob, history=[])
127
+ assert_equal true, result, "perform returned true"
128
+ assert_equal [:around_perform, :around_perform_plugin1, :perform], history
129
+ end
130
+
131
+ module AroundPerformPlugin2
132
+ def around_perform2(history)
133
+ history << :around_perform_plugin2
134
+ yield
135
+ end
136
+ end
137
+
138
+ class AroundPerformJob2
139
+ extend AroundPerformPlugin1
140
+ extend AroundPerformPlugin2
141
+ def self.perform(history)
142
+ history << :perform
143
+ end
144
+ def self.around_perform(history)
145
+ history << :around_perform
146
+ yield
147
+ end
148
+ end
149
+
150
+ test "many around_perform are executed in order" do
151
+ result = perform_job(AroundPerformJob2, history=[])
152
+ assert_equal true, result, "perform returned true"
153
+ assert_equal [:around_perform, :around_perform_plugin1, :around_perform_plugin2, :perform], history
154
+ end
155
+
156
+ module AroundPerformDoesNotYield
157
+ def around_perform0(history)
158
+ history << :around_perform0
159
+ end
160
+ end
161
+
162
+ class AroundPerformJob3
163
+ extend AroundPerformPlugin1
164
+ extend AroundPerformPlugin2
165
+ extend AroundPerformDoesNotYield
166
+ def self.perform(history)
167
+ history << :perform
168
+ end
169
+ def self.around_perform(history)
170
+ history << :around_perform
171
+ yield
172
+ end
173
+ end
174
+
175
+ test "the job is aborted if an around_perform hook does not yield" do
176
+ result = perform_job(AroundPerformJob3, history=[])
177
+ assert_equal false, result, "perform returned false"
178
+ assert_equal [:around_perform, :around_perform0], history
179
+ end
180
+ end
181
+
182
+ context "Resque::Plugin ordering on_failure" do
183
+ include PerformJob
184
+
185
+ module OnFailurePlugin
186
+ def on_failure1(exception, history)
187
+ history << "#{exception.message} plugin"
188
+ end
189
+ end
190
+
191
+ class FailureJob
192
+ extend OnFailurePlugin
193
+ def self.perform(history)
194
+ history << :perform
195
+ raise StandardError, "oh no"
196
+ end
197
+ def self.on_failure(exception, history)
198
+ history << exception.message
199
+ end
200
+ end
201
+
202
+ test "on_failure hooks are executed in order" do
203
+ history = []
204
+ assert_raises StandardError do
205
+ perform_job(FailureJob, history)
206
+ end
207
+ assert_equal [:perform, "oh no", "oh no plugin"], history
208
+ end
209
+ end
@@ -0,0 +1,116 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Resque::Plugin finding hooks" do
4
+ module SimplePlugin
5
+ extend self
6
+ def before_perform1; end
7
+ def before_perform; end
8
+ def before_perform2; end
9
+ def after_perform1; end
10
+ def after_perform; end
11
+ def after_perform2; end
12
+ def perform; end
13
+ def around_perform1; end
14
+ def around_perform; end
15
+ def around_perform2; end
16
+ def on_failure1; end
17
+ def on_failure; end
18
+ def on_failure2; end
19
+ end
20
+
21
+ test "before_perform hooks are found and sorted" do
22
+ assert_equal ["before_perform", "before_perform1", "before_perform2"], Resque::Plugin.before_hooks(SimplePlugin)
23
+ end
24
+
25
+ test "after_perform hooks are found and sorted" do
26
+ assert_equal ["after_perform", "after_perform1", "after_perform2"], Resque::Plugin.after_hooks(SimplePlugin)
27
+ end
28
+
29
+ test "around_perform hooks are found and sorted" do
30
+ assert_equal ["around_perform", "around_perform1", "around_perform2"], Resque::Plugin.around_hooks(SimplePlugin)
31
+ end
32
+
33
+ test "on_failure hooks are found and sorted" do
34
+ assert_equal ["on_failure", "on_failure1", "on_failure2"], Resque::Plugin.failure_hooks(SimplePlugin)
35
+ end
36
+ end
37
+
38
+ context "Resque::Plugin linting" do
39
+ module BadBefore
40
+ def self.before_perform; end
41
+ end
42
+ module BadAfter
43
+ def self.after_perform; end
44
+ end
45
+ module BadAround
46
+ def self.around_perform; end
47
+ end
48
+ module BadFailure
49
+ def self.on_failure; end
50
+ end
51
+
52
+ test "before_perform must be namespaced" do
53
+ begin
54
+ Resque::Plugin.lint(BadBefore)
55
+ assert false, "should have failed"
56
+ rescue Resque::Plugin::LintError => e
57
+ assert_equal "BadBefore.before_perform is not namespaced", e.message
58
+ end
59
+ end
60
+
61
+ test "after_perform must be namespaced" do
62
+ begin
63
+ Resque::Plugin.lint(BadAfter)
64
+ assert false, "should have failed"
65
+ rescue Resque::Plugin::LintError => e
66
+ assert_equal "BadAfter.after_perform is not namespaced", e.message
67
+ end
68
+ end
69
+
70
+ test "around_perform must be namespaced" do
71
+ begin
72
+ Resque::Plugin.lint(BadAround)
73
+ assert false, "should have failed"
74
+ rescue Resque::Plugin::LintError => e
75
+ assert_equal "BadAround.around_perform is not namespaced", e.message
76
+ end
77
+ end
78
+
79
+ test "on_failure must be namespaced" do
80
+ begin
81
+ Resque::Plugin.lint(BadFailure)
82
+ assert false, "should have failed"
83
+ rescue Resque::Plugin::LintError => e
84
+ assert_equal "BadFailure.on_failure is not namespaced", e.message
85
+ end
86
+ end
87
+
88
+ module GoodBefore
89
+ def self.before_perform1; end
90
+ end
91
+ module GoodAfter
92
+ def self.after_perform1; end
93
+ end
94
+ module GoodAround
95
+ def self.around_perform1; end
96
+ end
97
+ module GoodFailure
98
+ def self.on_failure1; end
99
+ end
100
+
101
+ test "before_perform1 is an ok name" do
102
+ Resque::Plugin.lint(GoodBefore)
103
+ end
104
+
105
+ test "after_perform1 is an ok name" do
106
+ Resque::Plugin.lint(GoodAfter)
107
+ end
108
+
109
+ test "around_perform1 is an ok name" do
110
+ Resque::Plugin.lint(GoodAround)
111
+ end
112
+
113
+ test "on_failure1 is an ok name" do
114
+ Resque::Plugin.lint(GoodFailure)
115
+ end
116
+ end
@@ -0,0 +1,62 @@
1
+ # ./test/resque-mongo_benchmark.rb
2
+
3
+ #require 'rubygems'
4
+ #require 'resque-mongo'
5
+ require File.join(File.dirname(__FILE__), 'test_helper')
6
+ require 'benchmark'
7
+
8
+ class SimpleJob
9
+ def self.perform
10
+ "Awesome"
11
+ end
12
+ end
13
+
14
+ class Job1 < SimpleJob
15
+ @queue = :q1
16
+ end
17
+
18
+ class Job2 < SimpleJob
19
+ @queue = :q2
20
+ end
21
+
22
+ class Job3 < SimpleJob
23
+ @queue = :q3
24
+ end
25
+
26
+ class Job4 < SimpleJob
27
+ @queue = :q4
28
+ end
29
+
30
+ class Array
31
+ def rand
32
+ self[Kernel.rand(length)]
33
+ end
34
+ end
35
+
36
+ a = [0,1,2,3,4,5,6]
37
+
38
+ Resque.drop
39
+
40
+ result = Benchmark.measure do
41
+ [Job1, Job2, Job3, Job4, Job3, Job2, Job1].each do |job|
42
+ 100.times do
43
+ Resque.enqueue(job)
44
+ end
45
+ end
46
+ end
47
+
48
+ puts "Enqueuing"
49
+ puts result
50
+
51
+ worker = Resque::Worker.new("q1", "q2", "q3", "q4")
52
+ result = Benchmark.measure { worker.work(0) }
53
+
54
+ puts "Working"
55
+ puts result
56
+
57
+ # With 7 000 entries
58
+ #
59
+ # Enqueuing
60
+ # 1.250000 0.150000 1.400000 ( 1.403977)
61
+ # Working
62
+ # 10.220000 1.020000 11.240000 ( 80.512621)
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'resque/server/test_helper'
3
+
4
+ # Root path test
5
+ context "on GET to /" do
6
+ setup { get "/" }
7
+
8
+ test "redirect to overview" do
9
+ follow_redirect!
10
+ end
11
+ end
12
+
13
+ # Global overview
14
+ context "on GET to /overview" do
15
+ setup { get "/overview" }
16
+
17
+ test "should at least display 'queues'" do
18
+ assert last_response.body.include?('Queues')
19
+ end
20
+ end
21
+
22
+ # Working jobs
23
+ context "on GET to /working" do
24
+ setup { get "/working" }
25
+
26
+ should_respond_with_success
27
+ end
28
+
29
+ # Failed
30
+ context "on GET to /failed" do
31
+ setup { get "/failed" }
32
+
33
+ should_respond_with_success
34
+ end
35
+
36
+ # Stats
37
+ context "on GET to /stats/resque" do
38
+ setup { get "/stats/resque" }
39
+
40
+ should_respond_with_success
41
+ end
42
+
43
+ context "on GET to /stats/redis" do
44
+ setup { get "/stats/redis" }
45
+
46
+ should_respond_with_success
47
+ end
48
+
49
+ context "on GET to /stats/resque" do
50
+ setup { get "/stats/keys" }
51
+
52
+ should_respond_with_success
53
+ end
54
+
@@ -50,12 +50,41 @@ context "Resque" do
50
50
  assert_equal nil, Resque.reserve(:ivar)
51
51
  end
52
52
 
53
+ test "can remove jobs from a queue by way of an ivar" do
54
+ assert_equal 0, Resque.size(:ivar)
55
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
56
+ assert Resque.enqueue(SomeIvarJob, 30, '/tmp')
57
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
58
+ assert Resque::Job.create(:ivar, 'blah-job', 20, '/tmp')
59
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
60
+ assert_equal 5, Resque.size(:ivar)
61
+
62
+ assert Resque.dequeue(SomeIvarJob, 30, '/tmp')
63
+ assert_equal 4, Resque.size(:ivar)
64
+ assert Resque.dequeue(SomeIvarJob)
65
+ assert_equal 1, Resque.size(:ivar)
66
+ end
67
+
53
68
  test "jobs have a nice #inspect" do
54
69
  assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
55
70
  job = Resque.reserve(:jobs)
56
71
  assert_equal '(Job{jobs} | SomeJob | [20, "/tmp"])', job.inspect
57
72
  end
58
73
 
74
+ test "jobs can be destroyed" do
75
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
76
+ assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp')
77
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
78
+ assert Resque::Job.create(:jobs, 'BadJob', 30, '/tmp')
79
+ assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp')
80
+
81
+ assert_equal 5, Resque.size(:jobs)
82
+ assert_equal 2, Resque::Job.destroy(:jobs, 'SomeJob')
83
+ assert_equal 3, Resque.size(:jobs)
84
+ assert_equal 1, Resque::Job.destroy(:jobs, 'BadJob', 30, '/tmp')
85
+ assert_equal 2, Resque.size(:jobs)
86
+ end
87
+
59
88
  test "jobs can test for equality" do
60
89
  assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
61
90
  assert Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
@@ -173,6 +202,7 @@ context "Resque" do
173
202
  @worker = Resque::Worker.new(:jobs)
174
203
  @worker.register_worker
175
204
  2.times { @worker.process }
205
+
176
206
  job = @worker.reserve
177
207
  @worker.working_on job
178
208
 
@@ -188,4 +218,8 @@ context "Resque" do
188
218
  assert_equal 1, stats[:failed]
189
219
  assert_equal ['localhost:27017'], stats[:servers]
190
220
  end
221
+
222
+ test "decode bad json" do
223
+ assert_nil Resque.decode("{\"error\":\"Module not found \\u002\"}")
224
+ end
191
225
  end