Skip to content

Commit f7623e3

Browse files
authored
Merge pull request #592 from Shopify/shutdown-enqueue
Gracefully shut down rufus scheduler threads
2 parents 0e0b271 + d00a2df commit f7623e3

5 files changed

Lines changed: 67 additions & 1 deletion

File tree

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Metrics/MethodLength:
3939
# Offense count: 2
4040
# Configuration parameters: CountComments.
4141
Metrics/ModuleLength:
42-
Max: 317
42+
Max: 322
4343

4444
# Offense count: 1
4545
Style/CaseEquality:

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ environment:
55
RUBYOPT: '-W0'
66
COVERAGE: 1
77
JRUBY_OPTS: ''
8+
TZ: 'UTC'
89

910
install:
1011
- set PATH=C:\Ruby23\bin;%PATH%

lib/resque/scheduler.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,13 @@ def handle_signals_with_operation
367367
true
368368
end
369369

370+
def stop_rufus_scheduler
371+
rufus_scheduler.shutdown(:wait)
372+
rufus_scheduler.join
373+
end
374+
370375
def before_shutdown
376+
stop_rufus_scheduler
371377
release_master_lock
372378
end
373379

resque-scheduler.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Gem::Specification.new do |spec|
4747
spec.add_development_dependency 'simplecov'
4848
spec.add_development_dependency 'test-unit'
4949
spec.add_development_dependency 'yard'
50+
spec.add_development_dependency 'tzinfo-data'
5051

5152
# We pin rubocop because new cops have a tendency to result in false-y
5253
# positives for new contributors, which is not a nice experience.

test/scheduler_test.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Resque.redis.flushall
1313
Resque::Scheduler.clear_schedule!
1414
Resque::Scheduler.send(:instance_variable_set, :@scheduled_jobs, {})
15+
Resque::Scheduler.send(:instance_variable_set, :@shutdown, false)
1516
end
1617

1718
test 'enqueue constantizes' do
@@ -456,6 +457,63 @@
456457
/#{Resque::Scheduler.send(:internal_name)}: cage/
457458
end
458459

460+
test 'gracefully shuts down rufus-scheduler threads' do
461+
if RUBY_ENGINE == 'jruby' || RUBY_PLATFORM =~ /mingw|windows/i
462+
omit("forking is not supported on #{RUBY_ENGINE}/#{RUBY_PLATFORM} but " \
463+
'this behaviour is best tested using forks')
464+
end
465+
466+
class BeforeEnqueueJob
467+
@queue = :quick
468+
469+
class << self
470+
def before_enqueue_example(*)
471+
return false if enqueue_started?
472+
enqueue_started!
473+
474+
sleep 5
475+
true
476+
end
477+
478+
def enqueue_started?
479+
Resque.redis.get('before_enqueue_job:enqueued') == 'true'
480+
end
481+
482+
def perform(*)
483+
end
484+
485+
private
486+
487+
def enqueue_started!
488+
Resque.redis.set('before_enqueue_job:enqueued', 'true')
489+
end
490+
end
491+
end
492+
493+
schedule = {
494+
'BeforeEnqueueJob' => { cron: '* * * * * *', class: 'BeforeEnqueueJob' }
495+
}
496+
497+
pid = fork do
498+
Resque::Scheduler.clear_schedule!
499+
Resque.schedule = schedule
500+
Resque::Scheduler.run
501+
end
502+
503+
begin
504+
30.times do
505+
break if BeforeEnqueueJob.enqueue_started?
506+
sleep 0.1
507+
end
508+
ensure
509+
Process.kill('TERM', pid)
510+
Process.wait(pid)
511+
end
512+
513+
assert BeforeEnqueueJob.enqueue_started?, "Job enqueue didn't start in time"
514+
assert_equal 1, Resque.size('quick')
515+
end
516+
459517
context 'printing schedule' do
460518
setup do
461519
Resque::Scheduler.expects(:log!).at_least_once

0 commit comments

Comments
 (0)