diff --git a/config/initializers/unicorn.rb b/config/initializers/unicorn.rb new file mode 100644 index 0000000..0874986 --- /dev/null +++ b/config/initializers/unicorn.rb @@ -0,0 +1,8 @@ +require_dependency 'scheduler/defer' + +if defined? Unicorn + ObjectSpace.each_object Unicorn::HttpServer do |s| + s.extend Scheduler::Defer::Unicorn + end +end + diff --git a/lib/noosfero/scheduler/defer.rb b/lib/noosfero/scheduler/defer.rb new file mode 100644 index 0000000..cdd1064 --- /dev/null +++ b/lib/noosfero/scheduler/defer.rb @@ -0,0 +1,95 @@ +# based on https://github.com/discourse/discourse/blob/master/lib/scheduler/defer.rb + +module Scheduler + module Deferrable + def initialize + # FIXME: do some other way when not using Unicorn + @async = (not Rails.env.test?) and defined? Unicorn + @queue = Queue.new + @mutex = Mutex.new + @paused = false + @thread = nil + end + + def pause + stop! + @paused = true + end + + def resume + @paused = false + end + + # for test + def async= val + @async = val + end + + def later desc = nil, &blk + if @async + start_thread unless (@thread && @thread.alive?) || @paused + @queue << [blk, desc] + else + blk.call + end + end + + def stop! + @thread.kill if @thread and @thread.alive? + @thread = nil + end + + # test only + def stopped? + !(@thread and @thread.alive?) + end + + def do_all_work + while !@queue.empty? + do_work _non_block=true + end + end + + private + + def start_thread + @mutex.synchronize do + return if @thread && @thread.alive? + @thread = Thread.new do + while true + do_work + end + end + @thread.priority = -2 + end + end + + # using non_block to match Ruby #deq + def do_work non_block=false + job, desc = @queue.deq non_block + begin + job.call + rescue => ex + ExceptionNotifier.notify_exception ex, message: "Running deferred code '#{desc}'" + end + rescue => ex + ExceptionNotifier.notify_exception ex, message: "Processing deferred code queue" + end + end + + class Defer + + module Unicorn + def process_client client + ::Scheduler::Defer.pause + super client + ::Scheduler::Defer.do_all_work + ::Scheduler::Defer.resume + end + end + + extend Deferrable + initialize + end + +end -- libgit2 0.21.2