diff --git a/lib/scheduler/defer.rb b/lib/scheduler/defer.rb index 46b94ee50..5c27c56b5 100644 --- a/lib/scheduler/defer.rb +++ b/lib/scheduler/defer.rb @@ -3,11 +3,10 @@ module Scheduler def initialize @async = Rails.env != "test" @queue = Queue.new - @thread = Thread.new { - while true - do_work - end - } + @mutex = Mutex.new + @thread = nil + start_thread + end # for test @@ -17,6 +16,7 @@ module Scheduler def later(&blk) if @async + start_thread unless @thread.alive? @queue << [RailsMultisite::ConnectionManagement.current_db, blk] else blk.call @@ -27,8 +27,24 @@ module Scheduler @thread.kill end + # test only + def stopped? + !@thread.alive? + end + private + def start_thread + @mutex.synchronize do + return if @thread && @thread.alive? + @thread = Thread.new { + while true + do_work + end + } + end + end + def do_work db, job = @queue.deq RailsMultisite::ConnectionManagement.establish_connection(db: db) diff --git a/spec/components/scheduler/defer_spec.rb b/spec/components/scheduler/defer_spec.rb index b27c36c3a..f564e94a0 100644 --- a/spec/components/scheduler/defer_spec.rb +++ b/spec/components/scheduler/defer_spec.rb @@ -23,6 +23,26 @@ describe Scheduler::Defer do @defer.stop! end + it "recovers from a crash / fork" do + s = nil + @defer.stop! + wait_for(10) do + @defer.stopped? + end + # hack allow thread to die + sleep 0.005 + + @defer.later do + s = "good" + end + + wait_for(10) do + s == "good" + end + + s.should == "good" + end + it "can queue jobs properly" do s = nil