resque-mongo 1.4.0 → 1.8.1

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.
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