opengotham_resque 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +2 -0
  2. data/.kick +26 -0
  3. data/HISTORY.md +142 -0
  4. data/LICENSE +20 -0
  5. data/README.markdown +794 -0
  6. data/Rakefile +112 -0
  7. data/bin/resque +57 -0
  8. data/bin/resque-web +23 -0
  9. data/config.ru +14 -0
  10. data/deps.rip +7 -0
  11. data/docs/HOOKS.md +121 -0
  12. data/docs/PLUGINS.md +93 -0
  13. data/examples/async_helper.rb +31 -0
  14. data/examples/demo/README.markdown +71 -0
  15. data/examples/demo/Rakefile +8 -0
  16. data/examples/demo/app.rb +38 -0
  17. data/examples/demo/config.ru +19 -0
  18. data/examples/demo/job.rb +22 -0
  19. data/examples/god/resque.god +53 -0
  20. data/examples/god/stale.god +26 -0
  21. data/examples/instance.rb +11 -0
  22. data/examples/monit/resque.monit +6 -0
  23. data/examples/simple.rb +30 -0
  24. data/init.rb +1 -0
  25. data/lib/resque.rb +287 -0
  26. data/lib/resque/errors.rb +10 -0
  27. data/lib/resque/failure.rb +66 -0
  28. data/lib/resque/failure/base.rb +61 -0
  29. data/lib/resque/failure/hoptoad.rb +132 -0
  30. data/lib/resque/failure/multiple.rb +48 -0
  31. data/lib/resque/failure/redis.rb +40 -0
  32. data/lib/resque/helpers.rb +63 -0
  33. data/lib/resque/job.rb +207 -0
  34. data/lib/resque/plugin.rb +46 -0
  35. data/lib/resque/server.rb +201 -0
  36. data/lib/resque/server/public/idle.png +0 -0
  37. data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
  38. data/lib/resque/server/public/jquery.relatize_date.js +95 -0
  39. data/lib/resque/server/public/poll.png +0 -0
  40. data/lib/resque/server/public/ranger.js +67 -0
  41. data/lib/resque/server/public/reset.css +48 -0
  42. data/lib/resque/server/public/style.css +81 -0
  43. data/lib/resque/server/public/working.png +0 -0
  44. data/lib/resque/server/test_helper.rb +19 -0
  45. data/lib/resque/server/views/error.erb +1 -0
  46. data/lib/resque/server/views/failed.erb +53 -0
  47. data/lib/resque/server/views/key_sets.erb +20 -0
  48. data/lib/resque/server/views/key_string.erb +11 -0
  49. data/lib/resque/server/views/layout.erb +44 -0
  50. data/lib/resque/server/views/next_more.erb +10 -0
  51. data/lib/resque/server/views/overview.erb +4 -0
  52. data/lib/resque/server/views/queues.erb +49 -0
  53. data/lib/resque/server/views/stats.erb +62 -0
  54. data/lib/resque/server/views/workers.erb +78 -0
  55. data/lib/resque/server/views/working.erb +69 -0
  56. data/lib/resque/stat.rb +53 -0
  57. data/lib/resque/tasks.rb +39 -0
  58. data/lib/resque/version.rb +3 -0
  59. data/lib/resque/worker.rb +478 -0
  60. data/tasks/redis.rake +159 -0
  61. data/tasks/resque.rake +2 -0
  62. data/test/job_hooks_test.rb +302 -0
  63. data/test/job_plugins_test.rb +209 -0
  64. data/test/plugin_test.rb +116 -0
  65. data/test/redis-test.conf +132 -0
  66. data/test/resque-web_test.rb +54 -0
  67. data/test/resque_test.rb +225 -0
  68. data/test/test_helper.rb +111 -0
  69. data/test/worker_test.rb +302 -0
  70. metadata +199 -0
@@ -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
+
@@ -0,0 +1,225 @@
1
+ require File.dirname(__FILE__) + '/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 put jobs on a queue" do
13
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
14
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
15
+ end
16
+
17
+ test "can grab jobs off a queue" do
18
+ Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
19
+
20
+ job = Resque.reserve(:jobs)
21
+
22
+ assert_kind_of Resque::Job, job
23
+ assert_equal SomeJob, job.payload_class
24
+ assert_equal 20, job.args[0]
25
+ assert_equal '/tmp', job.args[1]
26
+ end
27
+
28
+ test "can re-queue jobs" do
29
+ Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
30
+
31
+ job = Resque.reserve(:jobs)
32
+ job.recreate
33
+
34
+ assert_equal job, Resque.reserve(:jobs)
35
+ end
36
+
37
+ test "can put jobs on a queue by way of an ivar" do
38
+ assert_equal 0, Resque.size(:ivar)
39
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
40
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
41
+
42
+ job = Resque.reserve(:ivar)
43
+
44
+ assert_kind_of Resque::Job, job
45
+ assert_equal SomeIvarJob, job.payload_class
46
+ assert_equal 20, job.args[0]
47
+ assert_equal '/tmp', job.args[1]
48
+
49
+ assert Resque.reserve(:ivar)
50
+ assert_equal nil, Resque.reserve(:ivar)
51
+ end
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
+
68
+ test "jobs have a nice #inspect" do
69
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
70
+ job = Resque.reserve(:jobs)
71
+ assert_equal '(Job{jobs} | SomeJob | [20, "/tmp"])', job.inspect
72
+ end
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
+
88
+ test "jobs can test for equality" do
89
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
90
+ assert Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
91
+ assert_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
92
+
93
+ assert Resque::Job.create(:jobs, 'SomeMethodJob', 20, '/tmp')
94
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
95
+ assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
96
+
97
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
98
+ assert Resque::Job.create(:jobs, 'SomeJob', 30, '/tmp')
99
+ assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs)
100
+ end
101
+
102
+ test "can put jobs on a queue by way of a method" do
103
+ assert_equal 0, Resque.size(:method)
104
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
105
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
106
+
107
+ job = Resque.reserve(:method)
108
+
109
+ assert_kind_of Resque::Job, job
110
+ assert_equal SomeMethodJob, job.payload_class
111
+ assert_equal 20, job.args[0]
112
+ assert_equal '/tmp', job.args[1]
113
+
114
+ assert Resque.reserve(:method)
115
+ assert_equal nil, Resque.reserve(:method)
116
+ end
117
+
118
+ test "needs to infer a queue with enqueue" do
119
+ assert_raises Resque::NoQueueError do
120
+ Resque.enqueue(SomeJob, 20, '/tmp')
121
+ end
122
+ end
123
+
124
+ test "can put items on a queue" do
125
+ assert Resque.push(:people, { 'name' => 'jon' })
126
+ end
127
+
128
+ test "can pull items off a queue" do
129
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
130
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
131
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
132
+ assert_equal nil, Resque.pop(:people)
133
+ end
134
+
135
+ test "knows how big a queue is" do
136
+ assert_equal 3, Resque.size(:people)
137
+
138
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
139
+ assert_equal 2, Resque.size(:people)
140
+
141
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
142
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
143
+ assert_equal 0, Resque.size(:people)
144
+ end
145
+
146
+ test "can peek at a queue" do
147
+ assert_equal({ 'name' => 'chris' }, Resque.peek(:people))
148
+ assert_equal 3, Resque.size(:people)
149
+ end
150
+
151
+ test "can peek multiple items on a queue" do
152
+ assert_equal({ 'name' => 'bob' }, Resque.peek(:people, 1, 1))
153
+
154
+ assert_equal([{ 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 1, 2))
155
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }], Resque.peek(:people, 0, 2))
156
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 0, 3))
157
+ assert_equal({ 'name' => 'mark' }, Resque.peek(:people, 2, 1))
158
+ assert_equal nil, Resque.peek(:people, 3)
159
+ assert_equal [], Resque.peek(:people, 3, 2)
160
+ end
161
+
162
+ test "knows what queues it is managing" do
163
+ assert_equal %w( people ), Resque.queues
164
+ Resque.push(:cars, { 'make' => 'bmw' })
165
+ assert_equal %w( cars people ), Resque.queues
166
+ end
167
+
168
+ test "queues are always a list" do
169
+ Resque.redis.flushall
170
+ assert_equal [], Resque.queues
171
+ end
172
+
173
+ test "can delete a queue" do
174
+ Resque.push(:cars, { 'make' => 'bmw' })
175
+ assert_equal %w( cars people ), Resque.queues
176
+ Resque.remove_queue(:people)
177
+ assert_equal %w( cars ), Resque.queues
178
+ assert_equal nil, Resque.pop(:people)
179
+ end
180
+
181
+ test "keeps track of resque keys" do
182
+ assert_equal ["queue:people", "queues"], Resque.keys
183
+ end
184
+
185
+ test "badly wants a class name, too" do
186
+ assert_raises Resque::NoClassError do
187
+ Resque::Job.create(:jobs, nil)
188
+ end
189
+ end
190
+
191
+ test "keeps stats" do
192
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
193
+ Resque::Job.create(:jobs, BadJob)
194
+ Resque::Job.create(:jobs, GoodJob)
195
+
196
+ Resque::Job.create(:others, GoodJob)
197
+ Resque::Job.create(:others, GoodJob)
198
+
199
+ stats = Resque.info
200
+ assert_equal 8, stats[:pending]
201
+
202
+ @worker = Resque::Worker.new(:jobs)
203
+ @worker.register_worker
204
+ 2.times { @worker.process }
205
+
206
+ job = @worker.reserve
207
+ @worker.working_on job
208
+
209
+ stats = Resque.info
210
+ assert_equal 1, stats[:working]
211
+ assert_equal 1, stats[:workers]
212
+
213
+ @worker.done_working
214
+
215
+ stats = Resque.info
216
+ assert_equal 3, stats[:queues]
217
+ assert_equal 3, stats[:processed]
218
+ assert_equal 1, stats[:failed]
219
+ assert_equal ['localhost:9736'], stats[:servers]
220
+ end
221
+
222
+ test "decode bad json" do
223
+ assert_nil Resque.decode("{\"error\":\"Module not found \\u002\"}")
224
+ end
225
+ end
@@ -0,0 +1,111 @@
1
+ dir = File.dirname(File.expand_path(__FILE__))
2
+ $LOAD_PATH.unshift dir + '/../lib'
3
+ $TESTING = true
4
+ require 'test/unit'
5
+ require 'rubygems'
6
+ require 'resque'
7
+
8
+
9
+ #
10
+ # make sure we can run redis
11
+ #
12
+
13
+ if !system("which redis-server")
14
+ puts '', "** can't find `redis-server` in your path"
15
+ puts "** try running `sudo rake install`"
16
+ abort ''
17
+ end
18
+
19
+
20
+ #
21
+ # start our own redis when the tests start,
22
+ # kill it when they end
23
+ #
24
+
25
+ at_exit do
26
+ next if $!
27
+
28
+ if defined?(MiniTest)
29
+ exit_code = MiniTest::Unit.new.run(ARGV)
30
+ else
31
+ exit_code = Test::Unit::AutoRunner.run
32
+ end
33
+
34
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
35
+ puts "Killing test redis server..."
36
+ `rm -f #{dir}/dump.rdb`
37
+ Process.kill("KILL", pid.to_i)
38
+ exit exit_code
39
+ end
40
+
41
+ puts "Starting redis for testing at localhost:9736..."
42
+ `redis-server #{dir}/redis-test.conf`
43
+ Resque.redis = 'localhost:9736'
44
+
45
+
46
+ ##
47
+ # test/spec/mini 3
48
+ # http://gist.github.com/25455
49
+ # chris@ozmm.org
50
+ #
51
+ def context(*args, &block)
52
+ return super unless (name = args.first) && block
53
+ require 'test/unit'
54
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
55
+ def self.test(name, &block)
56
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
57
+ end
58
+ def self.xtest(*args) end
59
+ def self.setup(&block) define_method(:setup, &block) end
60
+ def self.teardown(&block) define_method(:teardown, &block) end
61
+ end
62
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
63
+ klass.class_eval &block
64
+ end
65
+
66
+ ##
67
+ # Helper to perform job classes
68
+ #
69
+ module PerformJob
70
+ def perform_job(klass, *args)
71
+ resque_job = Resque::Job.new(:testqueue, 'class' => klass, 'args' => args)
72
+ resque_job.perform
73
+ end
74
+ end
75
+
76
+ #
77
+ # fixture classes
78
+ #
79
+
80
+ class SomeJob
81
+ def self.perform(repo_id, path)
82
+ end
83
+ end
84
+
85
+ class SomeIvarJob < SomeJob
86
+ @queue = :ivar
87
+ end
88
+
89
+ class SomeMethodJob < SomeJob
90
+ def self.queue
91
+ :method
92
+ end
93
+ end
94
+
95
+ class BadJob
96
+ def self.perform
97
+ raise "Bad job!"
98
+ end
99
+ end
100
+
101
+ class GoodJob
102
+ def self.perform(name)
103
+ "Good job, #{name}"
104
+ end
105
+ end
106
+
107
+ class BadJobWithSyntaxError
108
+ def self.perform
109
+ raise SyntaxError, "Extra Bad job!"
110
+ end
111
+ end
@@ -0,0 +1,302 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Resque::Worker" do
4
+ setup do
5
+ Resque.redis.flushall
6
+
7
+ Resque.before_first_fork = nil
8
+ Resque.before_fork = nil
9
+ Resque.after_fork = nil
10
+
11
+ @worker = Resque::Worker.new(:jobs)
12
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
13
+ end
14
+
15
+ test "can fail jobs" do
16
+ Resque::Job.create(:jobs, BadJob)
17
+ @worker.work(0)
18
+ assert_equal 1, Resque::Failure.count
19
+ end
20
+
21
+ test "failed jobs report exception and message" do
22
+ Resque::Job.create(:jobs, BadJobWithSyntaxError)
23
+ @worker.work(0)
24
+ assert_equal('SyntaxError', Resque::Failure.all['exception'])
25
+ assert_equal('Extra Bad job!', Resque::Failure.all['error'])
26
+ end
27
+
28
+ test "fails uncompleted jobs on exit" do
29
+ job = Resque::Job.new(:jobs, [GoodJob, "blah"])
30
+ @worker.working_on(job)
31
+ @worker.unregister_worker
32
+ assert_equal 1, Resque::Failure.count
33
+ end
34
+
35
+ test "can peek at failed jobs" do
36
+ 10.times { Resque::Job.create(:jobs, BadJob) }
37
+ @worker.work(0)
38
+ assert_equal 10, Resque::Failure.count
39
+
40
+ assert_equal 10, Resque::Failure.all(0, 20).size
41
+ end
42
+
43
+ test "can clear failed jobs" do
44
+ Resque::Job.create(:jobs, BadJob)
45
+ @worker.work(0)
46
+ assert_equal 1, Resque::Failure.count
47
+ Resque::Failure.clear
48
+ assert_equal 0, Resque::Failure.count
49
+ end
50
+
51
+ test "catches exceptional jobs" do
52
+ Resque::Job.create(:jobs, BadJob)
53
+ Resque::Job.create(:jobs, BadJob)
54
+ @worker.process
55
+ @worker.process
56
+ @worker.process
57
+ assert_equal 2, Resque::Failure.count
58
+ end
59
+
60
+ test "can work on multiple queues" do
61
+ Resque::Job.create(:high, GoodJob)
62
+ Resque::Job.create(:critical, GoodJob)
63
+
64
+ worker = Resque::Worker.new(:critical, :high)
65
+
66
+ worker.process
67
+ assert_equal 1, Resque.size(:high)
68
+ assert_equal 0, Resque.size(:critical)
69
+
70
+ worker.process
71
+ assert_equal 0, Resque.size(:high)
72
+ end
73
+
74
+ test "can work on all queues" do
75
+ Resque::Job.create(:high, GoodJob)
76
+ Resque::Job.create(:critical, GoodJob)
77
+ Resque::Job.create(:blahblah, GoodJob)
78
+
79
+ worker = Resque::Worker.new("*")
80
+
81
+ worker.work(0)
82
+ assert_equal 0, Resque.size(:high)
83
+ assert_equal 0, Resque.size(:critical)
84
+ assert_equal 0, Resque.size(:blahblah)
85
+ end
86
+
87
+ test "processes * queues in alphabetical order" do
88
+ Resque::Job.create(:high, GoodJob)
89
+ Resque::Job.create(:critical, GoodJob)
90
+ Resque::Job.create(:blahblah, GoodJob)
91
+
92
+ worker = Resque::Worker.new("*")
93
+ processed_queues = []
94
+
95
+ worker.work(0) do |job|
96
+ processed_queues << job.queue
97
+ end
98
+
99
+ assert_equal %w( jobs high critical blahblah ).sort, processed_queues
100
+ end
101
+
102
+ test "has a unique id" do
103
+ assert_equal "#{`hostname`.chomp}:#{$$}:jobs", @worker.to_s
104
+ end
105
+
106
+ test "complains if no queues are given" do
107
+ assert_raise Resque::NoQueueError do
108
+ Resque::Worker.new
109
+ end
110
+ end
111
+
112
+ test "fails if a job class has no `perform` method" do
113
+ worker = Resque::Worker.new(:perform_less)
114
+ Resque::Job.create(:perform_less, Object)
115
+
116
+ assert_equal 0, Resque::Failure.count
117
+ worker.work(0)
118
+ assert_equal 1, Resque::Failure.count
119
+ end
120
+
121
+ test "inserts itself into the 'workers' list on startup" do
122
+ @worker.work(0) do
123
+ assert_equal @worker, Resque.workers[0]
124
+ end
125
+ end
126
+
127
+ test "removes itself from the 'workers' list on shutdown" do
128
+ @worker.work(0) do
129
+ assert_equal @worker, Resque.workers[0]
130
+ end
131
+
132
+ assert_equal [], Resque.workers
133
+ end
134
+
135
+ test "removes worker with stringified id" do
136
+ @worker.work(0) do
137
+ worker_id = Resque.workers[0].to_s
138
+ Resque.remove_worker(worker_id)
139
+ assert_equal [], Resque.workers
140
+ end
141
+ end
142
+
143
+ test "records what it is working on" do
144
+ @worker.work(0) do
145
+ task = @worker.job
146
+ assert_equal({"args"=>[20, "/tmp"], "class"=>"SomeJob"}, task['payload'])
147
+ assert task['run_at']
148
+ assert_equal 'jobs', task['queue']
149
+ end
150
+ end
151
+
152
+ test "clears its status when not working on anything" do
153
+ @worker.work(0)
154
+ assert_equal Hash.new, @worker.job
155
+ end
156
+
157
+ test "knows when it is working" do
158
+ @worker.work(0) do
159
+ assert @worker.working?
160
+ end
161
+ end
162
+
163
+ test "knows when it is idle" do
164
+ @worker.work(0)
165
+ assert @worker.idle?
166
+ end
167
+
168
+ test "knows who is working" do
169
+ @worker.work(0) do
170
+ assert_equal [@worker], Resque.working
171
+ end
172
+ end
173
+
174
+ test "keeps track of how many jobs it has processed" do
175
+ Resque::Job.create(:jobs, BadJob)
176
+ Resque::Job.create(:jobs, BadJob)
177
+
178
+ 3.times do
179
+ job = @worker.reserve
180
+ @worker.process job
181
+ end
182
+ assert_equal 3, @worker.processed
183
+ end
184
+
185
+ test "keeps track of how many failures it has seen" do
186
+ Resque::Job.create(:jobs, BadJob)
187
+ Resque::Job.create(:jobs, BadJob)
188
+
189
+ 3.times do
190
+ job = @worker.reserve
191
+ @worker.process job
192
+ end
193
+ assert_equal 2, @worker.failed
194
+ end
195
+
196
+ test "stats are erased when the worker goes away" do
197
+ @worker.work(0)
198
+ assert_equal 0, @worker.processed
199
+ assert_equal 0, @worker.failed
200
+ end
201
+
202
+ test "knows when it started" do
203
+ time = Time.now
204
+ @worker.work(0) do
205
+ assert_equal time.to_s, @worker.started.to_s
206
+ end
207
+ end
208
+
209
+ test "knows whether it exists or not" do
210
+ @worker.work(0) do
211
+ assert Resque::Worker.exists?(@worker)
212
+ assert !Resque::Worker.exists?('blah-blah')
213
+ end
214
+ end
215
+
216
+ test "sets $0 while working" do
217
+ @worker.work(0) do
218
+ ver = Resque::Version
219
+ assert_equal "resque-#{ver}: Processing jobs since #{Time.now.to_i}", $0
220
+ end
221
+ end
222
+
223
+ test "can be found" do
224
+ @worker.work(0) do
225
+ found = Resque::Worker.find(@worker.to_s)
226
+ assert_equal @worker.to_s, found.to_s
227
+ assert found.working?
228
+ assert_equal @worker.job, found.job
229
+ end
230
+ end
231
+
232
+ test "doesn't find fakes" do
233
+ @worker.work(0) do
234
+ found = Resque::Worker.find('blah-blah')
235
+ assert_equal nil, found
236
+ end
237
+ end
238
+
239
+ test "cleans up dead worker info on start (crash recovery)" do
240
+ # first we fake out two dead workers
241
+ workerA = Resque::Worker.new(:jobs)
242
+ workerA.instance_variable_set(:@to_s, "#{`hostname`.chomp}:1:jobs")
243
+ workerA.register_worker
244
+
245
+ workerB = Resque::Worker.new(:high, :low)
246
+ workerB.instance_variable_set(:@to_s, "#{`hostname`.chomp}:2:high,low")
247
+ workerB.register_worker
248
+
249
+ assert_equal 2, Resque.workers.size
250
+
251
+ # then we prune them
252
+ @worker.work(0) do
253
+ assert_equal 1, Resque.workers.size
254
+ end
255
+ end
256
+
257
+ test "Processed jobs count" do
258
+ @worker.work(0)
259
+ assert_equal 1, Resque.info[:processed]
260
+ end
261
+
262
+ test "Will call a before_first_fork hook only once" do
263
+ Resque.redis.flushall
264
+ $BEFORE_FORK_CALLED = 0
265
+ Resque.before_first_fork = Proc.new { $BEFORE_FORK_CALLED += 1 }
266
+ workerA = Resque::Worker.new(:jobs)
267
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
268
+
269
+ assert_equal 0, $BEFORE_FORK_CALLED
270
+
271
+ workerA.work(0)
272
+ assert_equal 1, $BEFORE_FORK_CALLED
273
+
274
+ # TODO: Verify it's only run once. Not easy.
275
+ # workerA.work(0)
276
+ # assert_equal 1, $BEFORE_FORK_CALLED
277
+ end
278
+
279
+ test "Will call a before_fork hook before forking" do
280
+ Resque.redis.flushall
281
+ $BEFORE_FORK_CALLED = false
282
+ Resque.before_fork = Proc.new { $BEFORE_FORK_CALLED = true }
283
+ workerA = Resque::Worker.new(:jobs)
284
+
285
+ assert !$BEFORE_FORK_CALLED
286
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
287
+ workerA.work(0)
288
+ assert $BEFORE_FORK_CALLED
289
+ end
290
+
291
+ test "Will call an after_fork hook after forking" do
292
+ Resque.redis.flushall
293
+ $AFTER_FORK_CALLED = false
294
+ Resque.after_fork = Proc.new { $AFTER_FORK_CALLED = true }
295
+ workerA = Resque::Worker.new(:jobs)
296
+
297
+ assert !$AFTER_FORK_CALLED
298
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
299
+ workerA.work(0)
300
+ assert $AFTER_FORK_CALLED
301
+ end
302
+ end