2014-08-18 23:04:58 -05:00
|
|
|
require 'thread'
|
|
|
|
|
|
|
|
class SidekiqPauser
|
|
|
|
def initialize
|
|
|
|
@mutex = Mutex.new
|
|
|
|
end
|
|
|
|
|
|
|
|
def pause!
|
2014-08-19 00:50:17 -05:00
|
|
|
redis.setex paused_key, 60, "paused"
|
2018-07-09 20:53:25 -05:00
|
|
|
|
2014-08-18 23:04:58 -05:00
|
|
|
@mutex.synchronize do
|
2014-08-19 00:50:17 -05:00
|
|
|
@extend_lease_thread ||= extend_lease_thread
|
2014-08-18 23:04:58 -05:00
|
|
|
sleep 0.001 while !paused?
|
|
|
|
end
|
2014-02-12 22:27:04 -06:00
|
|
|
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2014-08-18 23:04:58 -05:00
|
|
|
def paused?
|
2014-08-19 00:50:17 -05:00
|
|
|
!!redis.get(paused_key)
|
2014-02-12 22:27:04 -06:00
|
|
|
end
|
|
|
|
|
2014-08-18 23:04:58 -05:00
|
|
|
def unpause!
|
|
|
|
@mutex.synchronize do
|
2014-08-19 05:56:25 -05:00
|
|
|
@extend_lease_thread = nil
|
2014-08-18 23:04:58 -05:00
|
|
|
end
|
|
|
|
|
2014-08-19 00:50:17 -05:00
|
|
|
redis.del(paused_key)
|
2014-02-12 22:27:04 -06:00
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2014-08-19 00:50:17 -05:00
|
|
|
def extend_lease_thread
|
2014-08-18 23:04:58 -05:00
|
|
|
Thread.new do
|
2014-08-19 00:50:17 -05:00
|
|
|
while true do
|
2014-08-19 05:56:25 -05:00
|
|
|
break unless @mutex.synchronize { @extend_lease_thread }
|
2014-08-19 00:50:17 -05:00
|
|
|
redis.expire paused_key, 60
|
2018-07-09 20:53:25 -05:00
|
|
|
sleep(Rails.env.test? ? 0.01 : 30)
|
2014-08-18 23:04:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-19 00:50:17 -05:00
|
|
|
def redis
|
|
|
|
$redis.without_namespace
|
|
|
|
end
|
|
|
|
|
2014-08-18 23:04:58 -05:00
|
|
|
def paused_key
|
|
|
|
"sidekiq_is_paused_v2"
|
2014-02-12 22:27:04 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2014-08-18 23:04:58 -05:00
|
|
|
module Sidekiq
|
|
|
|
@pauser = SidekiqPauser.new
|
|
|
|
def self.pause!
|
|
|
|
@pauser.pause!
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.paused?
|
|
|
|
@pauser.paused?
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.unpause!
|
|
|
|
@pauser.unpause!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-12 22:27:04 -06:00
|
|
|
# server middleware that will reschedule work whenever Sidekiq is paused
|
|
|
|
class Sidekiq::Pausable
|
|
|
|
|
|
|
|
def initialize(delay = 5.seconds)
|
|
|
|
@delay = delay
|
|
|
|
end
|
|
|
|
|
|
|
|
def call(worker, msg, queue)
|
2018-08-28 21:36:59 -05:00
|
|
|
if Sidekiq.paused? && !(Jobs::RunHeartbeat === worker)
|
2016-01-11 11:31:28 -06:00
|
|
|
worker.class.perform_in(@delay, *msg['args'])
|
2014-02-12 22:27:04 -06:00
|
|
|
else
|
2017-10-23 01:30:17 -05:00
|
|
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
|
|
result = yield
|
|
|
|
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
|
|
DiscourseEvent.trigger(:sidekiq_job_ran, worker, msg, queue, duration)
|
|
|
|
result
|
2014-02-12 22:27:04 -06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|