resque 1.22.0 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of resque might be problematic. Click here for more details.
- data/HISTORY.md +7 -0
- data/lib/resque/version.rb +1 -1
- data/lib/resque/worker.rb +37 -13
- data/test/resque_failure_redis_test.rb +0 -4
- data/test/test_helper.rb +12 -8
- data/test/worker_test.rb +74 -5
- metadata +4 -5
- data/test/dump.rdb +0 -0
data/HISTORY.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 1.23.0 (2012-10-01)
|
2
|
+
|
3
|
+
* don't run `before_fork` hook if Resque can't fork (@kjwierenga, @tarcieri, #672, #697)
|
4
|
+
* don't run `after_fork` hook if Resque can't fork (@kjwierenga, @tarcieri, #672, #697)
|
5
|
+
* retry connecting to redis up to 3 times (@trevorturk, #693)
|
6
|
+
* pass exceptions raised by the worker into the Failure backend (@trevorturk, #693)
|
7
|
+
|
1
8
|
## 1.22.0 (2012-08-21)
|
2
9
|
|
3
10
|
* unregister signal handlers in child process when ENV["TERM_CHILD"] is set (@dylanasmith, #621)
|
data/lib/resque/version.rb
CHANGED
data/lib/resque/worker.rb
CHANGED
@@ -136,10 +136,9 @@ module Resque
|
|
136
136
|
if not paused? and job = reserve
|
137
137
|
log "got: #{job.inspect}"
|
138
138
|
job.worker = self
|
139
|
-
run_hook :before_fork, job
|
140
139
|
working_on job
|
141
140
|
|
142
|
-
if @child = fork
|
141
|
+
if @child = fork(job)
|
143
142
|
srand # Reseeding
|
144
143
|
procline "Forked #{@child} at #{Time.now.to_i}"
|
145
144
|
begin
|
@@ -148,11 +147,11 @@ module Resque
|
|
148
147
|
nil
|
149
148
|
end
|
150
149
|
else
|
151
|
-
unregister_signal_handlers if
|
150
|
+
unregister_signal_handlers if will_fork? && term_child
|
152
151
|
procline "Processing #{job.queue} since #{Time.now.to_i}"
|
153
|
-
|
152
|
+
reconnect
|
154
153
|
perform(job, &block)
|
155
|
-
exit!
|
154
|
+
exit! if will_fork?
|
156
155
|
end
|
157
156
|
|
158
157
|
done_working
|
@@ -165,8 +164,9 @@ module Resque
|
|
165
164
|
end
|
166
165
|
end
|
167
166
|
|
168
|
-
ensure
|
169
167
|
unregister_worker
|
168
|
+
rescue Exception => exception
|
169
|
+
unregister_worker(exception)
|
170
170
|
end
|
171
171
|
|
172
172
|
# DEPRECATED. Processes a single job. If none is given, it will
|
@@ -184,7 +184,7 @@ module Resque
|
|
184
184
|
# Processes a given job in the child.
|
185
185
|
def perform(job)
|
186
186
|
begin
|
187
|
-
run_hook :after_fork, job
|
187
|
+
run_hook :after_fork, job if will_fork?
|
188
188
|
job.perform
|
189
189
|
rescue Object => e
|
190
190
|
log "#{job.inspect} failed: #{e.inspect}"
|
@@ -219,6 +219,24 @@ module Resque
|
|
219
219
|
raise e
|
220
220
|
end
|
221
221
|
|
222
|
+
# Reconnect to Redis to avoid sharing a connection with the parent,
|
223
|
+
# retry up to 3 times with increasing delay before giving up.
|
224
|
+
def reconnect
|
225
|
+
tries = 0
|
226
|
+
begin
|
227
|
+
redis.client.reconnect
|
228
|
+
rescue Redis::BaseConnectionError
|
229
|
+
if (tries += 1) <= 3
|
230
|
+
log "Error reconnecting to Redis; retrying"
|
231
|
+
sleep(tries)
|
232
|
+
retry
|
233
|
+
else
|
234
|
+
log "Error reconnecting to Redis; quitting"
|
235
|
+
raise
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
222
240
|
# Returns a list of queues to use when searching for a job.
|
223
241
|
# A splat ("*") means you want every queue (in alpha order) - this
|
224
242
|
# can be useful for dynamically adding new queues.
|
@@ -228,15 +246,17 @@ module Resque
|
|
228
246
|
|
229
247
|
# Not every platform supports fork. Here we do our magic to
|
230
248
|
# determine if yours does.
|
231
|
-
def fork
|
232
|
-
@cant_fork = true if $TESTING
|
233
|
-
|
249
|
+
def fork(job)
|
234
250
|
return if @cant_fork
|
251
|
+
|
252
|
+
# Only run before_fork hooks if we're actually going to fork
|
253
|
+
# (after checking @cant_fork)
|
254
|
+
run_hook :before_fork, job
|
235
255
|
|
236
256
|
begin
|
237
257
|
# IronRuby doesn't support `Kernel.fork` yet
|
238
258
|
if Kernel.respond_to?(:fork)
|
239
|
-
Kernel.fork
|
259
|
+
Kernel.fork if will_fork?
|
240
260
|
else
|
241
261
|
raise NotImplementedError
|
242
262
|
end
|
@@ -424,7 +444,7 @@ module Resque
|
|
424
444
|
end
|
425
445
|
|
426
446
|
# Unregisters ourself as a worker. Useful when shutting down.
|
427
|
-
def unregister_worker
|
447
|
+
def unregister_worker(exception = nil)
|
428
448
|
# If we're still processing a job, make sure it gets logged as a
|
429
449
|
# failure.
|
430
450
|
if (hash = processing) && !hash.empty?
|
@@ -432,7 +452,7 @@ module Resque
|
|
432
452
|
# Ensure the proper worker is attached to this job, even if
|
433
453
|
# it's not the precise instance that died.
|
434
454
|
job.worker = self
|
435
|
-
job.fail(DirtyExit.new)
|
455
|
+
job.fail(exception || DirtyExit.new)
|
436
456
|
end
|
437
457
|
|
438
458
|
redis.srem(:workers, self)
|
@@ -507,6 +527,10 @@ module Resque
|
|
507
527
|
def idle?
|
508
528
|
state == :idle
|
509
529
|
end
|
530
|
+
|
531
|
+
def will_fork?
|
532
|
+
!(@cant_fork || $TESTING)
|
533
|
+
end
|
510
534
|
|
511
535
|
# Returns a symbol representing the current worker state,
|
512
536
|
# which can be either :working or :idle
|
@@ -13,10 +13,6 @@ context "Resque::Failure::Redis" do
|
|
13
13
|
|
14
14
|
test 'cleans up bad strings before saving the failure, in order to prevent errors on the resque UI' do
|
15
15
|
# test assumption: the bad string should not be able to round trip though JSON
|
16
|
-
assert_raises(MultiJson::DecodeError) {
|
17
|
-
MultiJson.decode(MultiJson.encode(@bad_string))
|
18
|
-
}
|
19
|
-
|
20
16
|
@redis_backend.save
|
21
17
|
Resque::Failure::Redis.all # should not raise an error
|
22
18
|
end
|
data/test/test_helper.rb
CHANGED
@@ -161,14 +161,18 @@ class Time
|
|
161
161
|
self.fake_time = nil
|
162
162
|
end
|
163
163
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
164
|
+
# From minitest/unit
|
165
|
+
def capture_io
|
166
|
+
require 'stringio'
|
167
|
+
|
168
|
+
orig_stdout, orig_stderr = $stdout, $stderr
|
169
|
+
captured_stdout, captured_stderr = StringIO.new, StringIO.new
|
170
|
+
$stdout, $stderr = captured_stdout, captured_stderr
|
171
|
+
|
169
172
|
yield
|
170
|
-
|
173
|
+
|
174
|
+
return captured_stdout.string, captured_stderr.string
|
171
175
|
ensure
|
172
|
-
|
173
|
-
$stderr =
|
176
|
+
$stdout = orig_stdout
|
177
|
+
$stderr = orig_stderr
|
174
178
|
end
|
data/test/worker_test.rb
CHANGED
@@ -32,11 +32,20 @@ context "Resque::Worker" do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
test "fails uncompleted jobs on exit" do
|
35
|
+
test "fails uncompleted jobs with DirtyExit by default on exit" do
|
36
36
|
job = Resque::Job.new(:jobs, {'class' => 'GoodJob', 'args' => "blah"})
|
37
37
|
@worker.working_on(job)
|
38
38
|
@worker.unregister_worker
|
39
39
|
assert_equal 1, Resque::Failure.count
|
40
|
+
assert_equal('Resque::DirtyExit', Resque::Failure.all['exception'])
|
41
|
+
end
|
42
|
+
|
43
|
+
test "fails uncompleted jobs with worker exception on exit" do
|
44
|
+
job = Resque::Job.new(:jobs, {'class' => 'GoodJob', 'args' => "blah"})
|
45
|
+
@worker.working_on(job)
|
46
|
+
@worker.unregister_worker(StandardError.new)
|
47
|
+
assert_equal 1, Resque::Failure.count
|
48
|
+
assert_equal('StandardError', Resque::Failure.all['exception'])
|
40
49
|
end
|
41
50
|
|
42
51
|
class ::SimpleJobWithFailureHandling
|
@@ -376,6 +385,19 @@ context "Resque::Worker" do
|
|
376
385
|
workerA.work(0)
|
377
386
|
assert $BEFORE_FORK_CALLED
|
378
387
|
end
|
388
|
+
|
389
|
+
test "Will not call a before_fork hook when the worker can't fork" do
|
390
|
+
Resque.redis.flushall
|
391
|
+
$BEFORE_FORK_CALLED = false
|
392
|
+
Resque.before_fork = Proc.new { $BEFORE_FORK_CALLED = true }
|
393
|
+
workerA = Resque::Worker.new(:jobs)
|
394
|
+
workerA.cant_fork = true
|
395
|
+
|
396
|
+
assert !$BEFORE_FORK_CALLED, "before_fork should not have been called before job runs"
|
397
|
+
Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
|
398
|
+
workerA.work(0)
|
399
|
+
assert !$BEFORE_FORK_CALLED, "before_fork should not have been called after job runs"
|
400
|
+
end
|
379
401
|
|
380
402
|
test "very verbose works in the afternoon" do
|
381
403
|
begin
|
@@ -396,16 +418,29 @@ context "Resque::Worker" do
|
|
396
418
|
end
|
397
419
|
end
|
398
420
|
|
399
|
-
test "Will call an after_fork hook
|
421
|
+
test "Will call an after_fork hook if we're forking" do
|
422
|
+
Resque.redis.flushall
|
423
|
+
$AFTER_FORK_CALLED = false
|
424
|
+
Resque.after_fork = Proc.new { $AFTER_FORK_CALLED = true }
|
425
|
+
workerA = Resque::Worker.new(:jobs)
|
426
|
+
|
427
|
+
assert !$AFTER_FORK_CALLED
|
428
|
+
Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
|
429
|
+
workerA.work(0)
|
430
|
+
assert $AFTER_FORK_CALLED == workerA.will_fork?
|
431
|
+
end
|
432
|
+
|
433
|
+
test "Will not call an after_fork hook when the worker can't fork" do
|
400
434
|
Resque.redis.flushall
|
401
435
|
$AFTER_FORK_CALLED = false
|
402
436
|
Resque.after_fork = Proc.new { $AFTER_FORK_CALLED = true }
|
403
437
|
workerA = Resque::Worker.new(:jobs)
|
438
|
+
workerA.cant_fork = true
|
404
439
|
|
405
440
|
assert !$AFTER_FORK_CALLED
|
406
441
|
Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
|
407
442
|
workerA.work(0)
|
408
|
-
assert
|
443
|
+
assert !$AFTER_FORK_CALLED
|
409
444
|
end
|
410
445
|
|
411
446
|
test "returns PID of running process" do
|
@@ -438,6 +473,40 @@ context "Resque::Worker" do
|
|
438
473
|
assert_not_equal original_connection, Resque.redis.client.connection.instance_variable_get("@sock")
|
439
474
|
end
|
440
475
|
|
476
|
+
test "tries to reconnect three times before giving up" do
|
477
|
+
begin
|
478
|
+
class Redis::Client
|
479
|
+
alias_method :original_reconnect, :reconnect
|
480
|
+
|
481
|
+
def reconnect
|
482
|
+
raise Redis::BaseConnectionError
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
class Resque::Worker
|
487
|
+
alias_method :original_sleep, :sleep
|
488
|
+
|
489
|
+
def sleep(duration = nil)
|
490
|
+
# noop
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
@worker.very_verbose = true
|
495
|
+
stdout, stderr = capture_io { @worker.work(0) }
|
496
|
+
|
497
|
+
assert_equal 3, stdout.scan(/retrying/).count
|
498
|
+
assert_equal 1, stdout.scan(/quitting/).count
|
499
|
+
ensure
|
500
|
+
class Redis::Client
|
501
|
+
alias_method :reconnect, :original_reconnect
|
502
|
+
end
|
503
|
+
|
504
|
+
class Resque::Worker
|
505
|
+
alias_method :sleep, :original_sleep
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
441
510
|
if !defined?(RUBY_ENGINE) || defined?(RUBY_ENGINE) && RUBY_ENGINE != "jruby"
|
442
511
|
test "old signal handling is the default" do
|
443
512
|
rescue_time = nil
|
@@ -573,14 +642,14 @@ context "Resque::Worker" do
|
|
573
642
|
end
|
574
643
|
|
575
644
|
test "displays warning when not using term_child" do
|
576
|
-
stderr =
|
645
|
+
stdout, stderr = capture_io { @worker.work(0) }
|
577
646
|
|
578
647
|
assert stderr.match(/^WARNING:/)
|
579
648
|
end
|
580
649
|
|
581
650
|
test "it does not display warning when using term_child" do
|
582
651
|
@worker.term_child = "1"
|
583
|
-
stderr =
|
652
|
+
stdout, stderr = capture_io { @worker.work(0) }
|
584
653
|
|
585
654
|
assert !stderr.match(/^WARNING:/)
|
586
655
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 75
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 23
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.23.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Chris Wanstrath
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-10-01 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: redis-namespace
|
@@ -151,7 +151,6 @@ files:
|
|
151
151
|
- test/test_helper.rb
|
152
152
|
- test/hoptoad_test.rb
|
153
153
|
- test/resque_test.rb
|
154
|
-
- test/dump.rdb
|
155
154
|
- test/job_plugins_test.rb
|
156
155
|
homepage: http://github.com/defunkt/resque
|
157
156
|
licenses: []
|
data/test/dump.rdb
DELETED
Binary file
|