steini-resque 1.18.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/HISTORY.md +322 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +881 -0
  4. data/Rakefile +78 -0
  5. data/bin/resque +81 -0
  6. data/bin/resque-web +23 -0
  7. data/lib/resque.rb +352 -0
  8. data/lib/resque/errors.rb +10 -0
  9. data/lib/resque/failure.rb +70 -0
  10. data/lib/resque/failure/base.rb +64 -0
  11. data/lib/resque/failure/hoptoad.rb +48 -0
  12. data/lib/resque/failure/multiple.rb +54 -0
  13. data/lib/resque/failure/redis.rb +51 -0
  14. data/lib/resque/helpers.rb +63 -0
  15. data/lib/resque/job.rb +205 -0
  16. data/lib/resque/plugin.rb +56 -0
  17. data/lib/resque/server.rb +231 -0
  18. data/lib/resque/server/public/favicon.ico +0 -0
  19. data/lib/resque/server/public/idle.png +0 -0
  20. data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
  21. data/lib/resque/server/public/jquery.relatize_date.js +95 -0
  22. data/lib/resque/server/public/poll.png +0 -0
  23. data/lib/resque/server/public/ranger.js +73 -0
  24. data/lib/resque/server/public/reset.css +48 -0
  25. data/lib/resque/server/public/style.css +85 -0
  26. data/lib/resque/server/public/working.png +0 -0
  27. data/lib/resque/server/test_helper.rb +19 -0
  28. data/lib/resque/server/views/error.erb +1 -0
  29. data/lib/resque/server/views/failed.erb +64 -0
  30. data/lib/resque/server/views/key_sets.erb +19 -0
  31. data/lib/resque/server/views/key_string.erb +11 -0
  32. data/lib/resque/server/views/layout.erb +44 -0
  33. data/lib/resque/server/views/next_more.erb +10 -0
  34. data/lib/resque/server/views/overview.erb +4 -0
  35. data/lib/resque/server/views/queues.erb +49 -0
  36. data/lib/resque/server/views/stats.erb +62 -0
  37. data/lib/resque/server/views/workers.erb +109 -0
  38. data/lib/resque/server/views/working.erb +72 -0
  39. data/lib/resque/stat.rb +53 -0
  40. data/lib/resque/tasks.rb +51 -0
  41. data/lib/resque/version.rb +3 -0
  42. data/lib/resque/worker.rb +533 -0
  43. data/lib/tasks/redis.rake +161 -0
  44. data/lib/tasks/resque.rake +2 -0
  45. data/test/hoptoad_test.rb +25 -0
  46. data/test/job_hooks_test.rb +363 -0
  47. data/test/job_plugins_test.rb +230 -0
  48. data/test/plugin_test.rb +116 -0
  49. data/test/redis-test.conf +115 -0
  50. data/test/resque-web_test.rb +53 -0
  51. data/test/resque_test.rb +259 -0
  52. data/test/test_helper.rb +148 -0
  53. data/test/worker_test.rb +332 -0
  54. metadata +183 -0
@@ -0,0 +1,53 @@
1
+ require '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
@@ -0,0 +1,259 @@
1
+ require 'test_helper'
2
+
3
+ context "Resque" do
4
+ setup do
5
+ Resque.redis.flushall
6
+
7
+ Resque.push(:people, { 'name' => 'chris' })
8
+ Resque.push(:people, { 'name' => 'bob' })
9
+ Resque.push(:people, { 'name' => 'mark' })
10
+ end
11
+
12
+ test "can set a namespace through a url-like string" do
13
+ assert Resque.redis
14
+ assert_equal :resque, Resque.redis.namespace
15
+ Resque.redis = 'localhost:9736/namespace'
16
+ assert_equal 'namespace', Resque.redis.namespace
17
+ end
18
+
19
+ test "redis= works correctly with a Redis::Namespace param" do
20
+ new_redis = Redis.new(:host => "localhost", :port => 9736)
21
+ new_namespace = Redis::Namespace.new("namespace", :redis => new_redis)
22
+ Resque.redis = new_namespace
23
+ assert_equal new_namespace, Resque.redis
24
+
25
+ Resque.redis = 'localhost:9736/namespace'
26
+ end
27
+
28
+ test "can put jobs on a queue" do
29
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
30
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
31
+ end
32
+
33
+ test "can grab jobs off a queue" do
34
+ Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
35
+
36
+ job = Resque.reserve(:jobs)
37
+
38
+ assert_kind_of Resque::Job, job
39
+ assert_equal SomeJob, job.payload_class
40
+ assert_equal 20, job.args[0]
41
+ assert_equal '/tmp', job.args[1]
42
+ end
43
+
44
+ test "can re-queue jobs" do
45
+ Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
46
+
47
+ job = Resque.reserve(:jobs)
48
+ job.recreate
49
+
50
+ assert_equal job, Resque.reserve(:jobs)
51
+ end
52
+
53
+ test "can put jobs on 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, 20, '/tmp')
57
+
58
+ job = Resque.reserve(:ivar)
59
+
60
+ assert_kind_of Resque::Job, job
61
+ assert_equal SomeIvarJob, job.payload_class
62
+ assert_equal 20, job.args[0]
63
+ assert_equal '/tmp', job.args[1]
64
+
65
+ assert Resque.reserve(:ivar)
66
+ assert_equal nil, Resque.reserve(:ivar)
67
+ end
68
+
69
+ test "can remove jobs from a queue by way of an ivar" do
70
+ assert_equal 0, Resque.size(:ivar)
71
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
72
+ assert Resque.enqueue(SomeIvarJob, 30, '/tmp')
73
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
74
+ assert Resque::Job.create(:ivar, 'blah-job', 20, '/tmp')
75
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
76
+ assert_equal 5, Resque.size(:ivar)
77
+
78
+ assert Resque.dequeue(SomeIvarJob, 30, '/tmp')
79
+ assert_equal 4, Resque.size(:ivar)
80
+ assert Resque.dequeue(SomeIvarJob)
81
+ assert_equal 1, Resque.size(:ivar)
82
+ end
83
+
84
+ test "jobs have a nice #inspect" do
85
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
86
+ job = Resque.reserve(:jobs)
87
+ assert_equal '(Job{jobs} | SomeJob | [20, "/tmp"])', job.inspect
88
+ end
89
+
90
+ test "jobs can be destroyed" do
91
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
92
+ assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp')
93
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
94
+ assert Resque::Job.create(:jobs, 'BadJob', 30, '/tmp')
95
+ assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp')
96
+
97
+ assert_equal 5, Resque.size(:jobs)
98
+ assert_equal 2, Resque::Job.destroy(:jobs, 'SomeJob')
99
+ assert_equal 3, Resque.size(:jobs)
100
+ assert_equal 1, Resque::Job.destroy(:jobs, 'BadJob', 30, '/tmp')
101
+ assert_equal 2, Resque.size(:jobs)
102
+ end
103
+
104
+ test "jobs can test for equality" do
105
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
106
+ assert Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
107
+ assert_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
108
+
109
+ assert Resque::Job.create(:jobs, 'SomeMethodJob', 20, '/tmp')
110
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
111
+ assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
112
+
113
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
114
+ assert Resque::Job.create(:jobs, 'SomeJob', 30, '/tmp')
115
+ assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
116
+ end
117
+
118
+ test "can put jobs on a queue by way of a method" do
119
+ assert_equal 0, Resque.size(:method)
120
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
121
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
122
+
123
+ job = Resque.reserve(:method)
124
+
125
+ assert_kind_of Resque::Job, job
126
+ assert_equal SomeMethodJob, job.payload_class
127
+ assert_equal 20, job.args[0]
128
+ assert_equal '/tmp', job.args[1]
129
+
130
+ assert Resque.reserve(:method)
131
+ assert_equal nil, Resque.reserve(:method)
132
+ end
133
+
134
+ test "needs to infer a queue with enqueue" do
135
+ assert_raises Resque::NoQueueError do
136
+ Resque.enqueue(SomeJob, 20, '/tmp')
137
+ end
138
+ end
139
+
140
+ test "validates job for queue presence" do
141
+ assert_raises Resque::NoQueueError do
142
+ Resque.validate(SomeJob)
143
+ end
144
+ end
145
+
146
+ test "can put items on a queue" do
147
+ assert Resque.push(:people, { 'name' => 'jon' })
148
+ end
149
+
150
+ test "can pull items off a queue" do
151
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
152
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
153
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
154
+ assert_equal nil, Resque.pop(:people)
155
+ end
156
+
157
+ test "knows how big a queue is" do
158
+ assert_equal 3, Resque.size(:people)
159
+
160
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
161
+ assert_equal 2, Resque.size(:people)
162
+
163
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
164
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
165
+ assert_equal 0, Resque.size(:people)
166
+ end
167
+
168
+ test "can peek at a queue" do
169
+ assert_equal({ 'name' => 'chris' }, Resque.peek(:people))
170
+ assert_equal 3, Resque.size(:people)
171
+ end
172
+
173
+ test "can peek multiple items on a queue" do
174
+ assert_equal({ 'name' => 'bob' }, Resque.peek(:people, 1, 1))
175
+
176
+ assert_equal([{ 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 1, 2))
177
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }], Resque.peek(:people, 0, 2))
178
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 0, 3))
179
+ assert_equal({ 'name' => 'mark' }, Resque.peek(:people, 2, 1))
180
+ assert_equal nil, Resque.peek(:people, 3)
181
+ assert_equal [], Resque.peek(:people, 3, 2)
182
+ end
183
+
184
+ test "knows what queues it is managing" do
185
+ assert_equal %w( people ), Resque.queues
186
+ Resque.push(:cars, { 'make' => 'bmw' })
187
+ assert_equal %w( cars people ), Resque.queues
188
+ end
189
+
190
+ test "queues are always a list" do
191
+ Resque.redis.flushall
192
+ assert_equal [], Resque.queues
193
+ end
194
+
195
+ test "can delete a queue" do
196
+ Resque.push(:cars, { 'make' => 'bmw' })
197
+ assert_equal %w( cars people ), Resque.queues
198
+ Resque.remove_queue(:people)
199
+ assert_equal %w( cars ), Resque.queues
200
+ assert_equal nil, Resque.pop(:people)
201
+ end
202
+
203
+ test "keeps track of resque keys" do
204
+ assert_equal ["queue:people", "queues"], Resque.keys
205
+ end
206
+
207
+ test "badly wants a class name, too" do
208
+ assert_raises Resque::NoClassError do
209
+ Resque::Job.create(:jobs, nil)
210
+ end
211
+ end
212
+
213
+ test "keeps stats" do
214
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
215
+ Resque::Job.create(:jobs, BadJob)
216
+ Resque::Job.create(:jobs, GoodJob)
217
+
218
+ Resque::Job.create(:others, GoodJob)
219
+ Resque::Job.create(:others, GoodJob)
220
+
221
+ stats = Resque.info
222
+ assert_equal 8, stats[:pending]
223
+
224
+ @worker = Resque::Worker.new(:jobs)
225
+ @worker.register_worker
226
+ 2.times { @worker.process }
227
+
228
+ job = @worker.reserve
229
+ @worker.working_on job
230
+
231
+ stats = Resque.info
232
+ assert_equal 1, stats[:working]
233
+ assert_equal 1, stats[:workers]
234
+
235
+ @worker.done_working
236
+
237
+ stats = Resque.info
238
+ assert_equal 3, stats[:queues]
239
+ assert_equal 3, stats[:processed]
240
+ assert_equal 1, stats[:failed]
241
+ assert_equal [Resque.redis.respond_to?(:server) ? 'localhost:9736' : 'redis://localhost:9736/0'], stats[:servers]
242
+ end
243
+
244
+ test "decode bad json" do
245
+ assert_raises Resque::Helpers::DecodeException do
246
+ Resque.decode("{\"error\":\"Module not found \\u002\"}")
247
+ end
248
+ end
249
+
250
+ test "inlining jobs" do
251
+ begin
252
+ Resque.inline = true
253
+ Resque.enqueue(SomeIvarJob, 20, '/tmp')
254
+ assert_equal 0, Resque.size(:ivar)
255
+ ensure
256
+ Resque.inline = false
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,148 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ dir = File.dirname(File.expand_path(__FILE__))
7
+ $LOAD_PATH.unshift dir + '/../lib'
8
+ $TESTING = true
9
+ require 'test/unit'
10
+
11
+ begin
12
+ require 'leftright'
13
+ rescue LoadError
14
+ end
15
+
16
+
17
+ #
18
+ # make sure we can run redis
19
+ #
20
+
21
+ if !system("which redis-server")
22
+ puts '', "** can't find `redis-server` in your path"
23
+ puts "** try running `sudo rake install`"
24
+ abort ''
25
+ end
26
+
27
+
28
+ #
29
+ # start our own redis when the tests start,
30
+ # kill it when they end
31
+ #
32
+
33
+ at_exit do
34
+ next if $!
35
+
36
+ if defined?(MiniTest)
37
+ exit_code = MiniTest::Unit.new.run(ARGV)
38
+ else
39
+ exit_code = Test::Unit::AutoRunner.run
40
+ end
41
+
42
+ pid = `ps -A -o pid,command | grep [r]edis-test`.split(" ")[0]
43
+ puts "Killing test redis server..."
44
+ `rm -f #{dir}/dump.rdb`
45
+ Process.kill("KILL", pid.to_i)
46
+ exit exit_code
47
+ end
48
+
49
+ puts "Starting redis for testing at localhost:9736..."
50
+ `redis-server #{dir}/redis-test.conf`
51
+ Resque.redis = 'localhost:9736'
52
+
53
+
54
+ ##
55
+ # test/spec/mini 3
56
+ # http://gist.github.com/25455
57
+ # chris@ozmm.org
58
+ #
59
+ def context(*args, &block)
60
+ return super unless (name = args.first) && block
61
+ require 'test/unit'
62
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
63
+ def self.test(name, &block)
64
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
65
+ end
66
+ def self.xtest(*args) end
67
+ def self.setup(&block) define_method(:setup, &block) end
68
+ def self.teardown(&block) define_method(:teardown, &block) end
69
+ end
70
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
71
+ klass.class_eval &block
72
+ # XXX: In 1.8.x, not all tests will run unless anonymous classes are kept in scope.
73
+ ($test_classes ||= []) << klass
74
+ end
75
+
76
+ ##
77
+ # Helper to perform job classes
78
+ #
79
+ module PerformJob
80
+ def perform_job(klass, *args)
81
+ resque_job = Resque::Job.new(:testqueue, 'class' => klass, 'args' => args)
82
+ resque_job.perform
83
+ end
84
+ end
85
+
86
+ #
87
+ # fixture classes
88
+ #
89
+
90
+ class SomeJob
91
+ def self.perform(repo_id, path)
92
+ end
93
+ end
94
+
95
+ class SomeIvarJob < SomeJob
96
+ @queue = :ivar
97
+ end
98
+
99
+ class SomeMethodJob < SomeJob
100
+ def self.queue
101
+ :method
102
+ end
103
+ end
104
+
105
+ class BadJob
106
+ def self.perform
107
+ raise "Bad job!"
108
+ end
109
+ end
110
+
111
+ class GoodJob
112
+ def self.perform(name)
113
+ "Good job, #{name}"
114
+ end
115
+ end
116
+
117
+ class BadJobWithSyntaxError
118
+ def self.perform
119
+ raise SyntaxError, "Extra Bad job!"
120
+ end
121
+ end
122
+
123
+ class BadFailureBackend < Resque::Failure::Base
124
+ def save
125
+ raise Exception.new("Failure backend error")
126
+ end
127
+ end
128
+
129
+ def with_failure_backend(failure_backend, &block)
130
+ previous_backend = Resque::Failure.backend
131
+ Resque::Failure.backend = failure_backend
132
+ yield block
133
+ ensure
134
+ Resque::Failure.backend = previous_backend
135
+ end
136
+
137
+ class Time
138
+ # Thanks, Timecop
139
+ class << self
140
+ alias_method :now_without_mock_time, :now
141
+
142
+ def now_with_mock_time
143
+ $fake_time || now_without_mock_time
144
+ end
145
+
146
+ alias_method :now, :now_with_mock_time
147
+ end
148
+ end