Commit cd9c0b0740f69da6696731a5ab38d61a9e09b514

Authored by Braulio Bhavamitra
1 parent 1a1eab27

scheduler: defer off-request work

config/initializers/unicorn.rb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +require_dependency 'scheduler/defer'
  2 +
  3 +if defined? Unicorn
  4 + ObjectSpace.each_object Unicorn::HttpServer do |s|
  5 + s.extend Scheduler::Defer::Unicorn
  6 + end
  7 +end
  8 +
... ...
lib/noosfero/scheduler/defer.rb 0 → 100644
... ... @@ -0,0 +1,95 @@
  1 +# based on https://github.com/discourse/discourse/blob/master/lib/scheduler/defer.rb
  2 +
  3 +module Scheduler
  4 + module Deferrable
  5 + def initialize
  6 + # FIXME: do some other way when not using Unicorn
  7 + @async = (not Rails.env.test?) and defined? Unicorn
  8 + @queue = Queue.new
  9 + @mutex = Mutex.new
  10 + @paused = false
  11 + @thread = nil
  12 + end
  13 +
  14 + def pause
  15 + stop!
  16 + @paused = true
  17 + end
  18 +
  19 + def resume
  20 + @paused = false
  21 + end
  22 +
  23 + # for test
  24 + def async= val
  25 + @async = val
  26 + end
  27 +
  28 + def later desc = nil, &blk
  29 + if @async
  30 + start_thread unless (@thread && @thread.alive?) || @paused
  31 + @queue << [blk, desc]
  32 + else
  33 + blk.call
  34 + end
  35 + end
  36 +
  37 + def stop!
  38 + @thread.kill if @thread and @thread.alive?
  39 + @thread = nil
  40 + end
  41 +
  42 + # test only
  43 + def stopped?
  44 + !(@thread and @thread.alive?)
  45 + end
  46 +
  47 + def do_all_work
  48 + while !@queue.empty?
  49 + do_work _non_block=true
  50 + end
  51 + end
  52 +
  53 + private
  54 +
  55 + def start_thread
  56 + @mutex.synchronize do
  57 + return if @thread && @thread.alive?
  58 + @thread = Thread.new do
  59 + while true
  60 + do_work
  61 + end
  62 + end
  63 + @thread.priority = -2
  64 + end
  65 + end
  66 +
  67 + # using non_block to match Ruby #deq
  68 + def do_work non_block=false
  69 + job, desc = @queue.deq non_block
  70 + begin
  71 + job.call
  72 + rescue => ex
  73 + ExceptionNotifier.notify_exception ex, message: "Running deferred code '#{desc}'"
  74 + end
  75 + rescue => ex
  76 + ExceptionNotifier.notify_exception ex, message: "Processing deferred code queue"
  77 + end
  78 + end
  79 +
  80 + class Defer
  81 +
  82 + module Unicorn
  83 + def process_client client
  84 + ::Scheduler::Defer.pause
  85 + super client
  86 + ::Scheduler::Defer.do_all_work
  87 + ::Scheduler::Defer.resume
  88 + end
  89 + end
  90 +
  91 + extend Deferrable
  92 + initialize
  93 + end
  94 +
  95 +end
... ...