opengotham_resque 1.8.2

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