2013-09-21 23:17:37 -04:00
|
|
|
require 'sidekiq/actor'
|
2013-01-29 11:15:34 -05:00
|
|
|
require 'sidekiq/manager'
|
2013-09-21 23:17:37 -04:00
|
|
|
require 'sidekiq/fetch'
|
2013-01-29 11:15:34 -05:00
|
|
|
require 'sidekiq/scheduled'
|
|
|
|
|
|
|
|
module Sidekiq
|
2013-09-21 20:05:16 -04:00
|
|
|
# The Launcher is a very simple Actor whose job is to
|
|
|
|
# start, monitor and stop the core Actors in Sidekiq.
|
|
|
|
# If any of these actors die, the Sidekiq process exits
|
|
|
|
# immediately.
|
2013-01-29 11:15:34 -05:00
|
|
|
class Launcher
|
2013-09-21 23:17:37 -04:00
|
|
|
include Actor
|
2013-09-22 17:05:29 -04:00
|
|
|
include Util
|
2013-09-21 20:05:16 -04:00
|
|
|
|
|
|
|
trap_exit :actor_died
|
|
|
|
|
|
|
|
attr_reader :manager, :poller, :fetcher
|
|
|
|
|
2013-01-29 11:15:34 -05:00
|
|
|
def initialize(options)
|
2014-11-18 13:50:42 -05:00
|
|
|
@condvar = Celluloid::Condition.new
|
|
|
|
@manager = Sidekiq::Manager.new_link(@condvar, options)
|
2013-09-21 20:05:16 -04:00
|
|
|
@poller = Sidekiq::Scheduled::Poller.new_link
|
2014-11-18 13:50:42 -05:00
|
|
|
@fetcher = Sidekiq::Fetcher.new_link(@manager, options)
|
2013-09-22 17:05:29 -04:00
|
|
|
@manager.fetcher = @fetcher
|
2013-09-21 20:05:16 -04:00
|
|
|
@done = false
|
2013-01-29 11:15:34 -05:00
|
|
|
@options = options
|
2013-09-21 20:05:16 -04:00
|
|
|
end
|
2013-09-21 10:51:49 -04:00
|
|
|
|
2013-09-21 20:05:16 -04:00
|
|
|
def actor_died(actor, reason)
|
2014-12-10 12:26:55 -05:00
|
|
|
# https://github.com/mperham/sidekiq/issues/2057#issuecomment-66485477
|
|
|
|
return if @done || !reason
|
|
|
|
|
2013-09-22 23:48:17 -04:00
|
|
|
Sidekiq.logger.warn("Sidekiq died due to the following error, cannot recover, process exiting")
|
|
|
|
handle_exception(reason)
|
2013-09-21 20:05:16 -04:00
|
|
|
exit(1)
|
2013-01-29 11:15:34 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def run
|
2013-09-22 23:48:17 -04:00
|
|
|
watchdog('Launcher#run') do
|
2013-09-22 17:05:29 -04:00
|
|
|
manager.async.start
|
|
|
|
poller.async.poll(true)
|
2014-03-21 11:53:22 -04:00
|
|
|
|
2014-03-21 23:46:14 -04:00
|
|
|
start_heartbeat
|
2013-09-22 17:05:29 -04:00
|
|
|
end
|
2013-01-29 11:15:34 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def stop
|
2013-09-22 17:05:29 -04:00
|
|
|
watchdog('Launcher#stop') do
|
|
|
|
@done = true
|
|
|
|
Sidekiq::Fetcher.done!
|
2014-01-10 11:56:20 -05:00
|
|
|
fetcher.terminate if fetcher.alive?
|
|
|
|
poller.terminate if poller.alive?
|
|
|
|
|
2014-01-10 14:58:53 -05:00
|
|
|
manager.async.stop(:shutdown => true, :timeout => @options[:timeout])
|
2014-11-18 13:50:42 -05:00
|
|
|
@condvar.wait
|
|
|
|
manager.terminate
|
2014-01-10 14:58:53 -05:00
|
|
|
|
2013-12-21 08:59:30 -05:00
|
|
|
# Requeue everything in case there was a worker who grabbed work while stopped
|
2014-09-10 13:43:06 -04:00
|
|
|
# This call is a no-op in Sidekiq but necessary for Sidekiq Pro.
|
2013-12-21 08:59:30 -05:00
|
|
|
Sidekiq::Fetcher.strategy.bulk_requeue([], @options)
|
2014-03-08 01:41:10 -05:00
|
|
|
|
|
|
|
stop_heartbeat
|
2013-09-22 17:05:29 -04:00
|
|
|
end
|
2013-01-29 11:15:34 -05:00
|
|
|
end
|
2013-01-29 11:43:44 -05:00
|
|
|
|
2014-03-21 11:53:22 -04:00
|
|
|
private
|
|
|
|
|
2014-03-21 23:46:14 -04:00
|
|
|
def start_heartbeat
|
2014-03-08 01:41:10 -05:00
|
|
|
key = identity
|
|
|
|
data = {
|
2014-03-02 19:36:00 -05:00
|
|
|
'hostname' => hostname,
|
2014-03-07 00:30:11 -05:00
|
|
|
'started_at' => Time.now.to_f,
|
2014-03-02 19:36:00 -05:00
|
|
|
'pid' => $$,
|
2014-03-21 23:46:14 -04:00
|
|
|
'tag' => @options[:tag] || '',
|
2014-03-02 19:36:00 -05:00
|
|
|
'concurrency' => @options[:concurrency],
|
|
|
|
'queues' => @options[:queues].uniq,
|
2014-05-31 17:11:28 -04:00
|
|
|
'labels' => Sidekiq.options[:labels],
|
2014-03-08 01:41:10 -05:00
|
|
|
}
|
2014-08-08 00:03:34 -04:00
|
|
|
# this data doesn't change so dump it to a string
|
|
|
|
# now so we don't need to dump it every heartbeat.
|
|
|
|
json = Sidekiq.dump_json(data)
|
|
|
|
manager.heartbeat(key, data, json)
|
2014-03-08 01:41:10 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def stop_heartbeat
|
|
|
|
Sidekiq.redis do |conn|
|
2014-06-06 11:37:23 -04:00
|
|
|
conn.pipelined do
|
|
|
|
conn.srem('processes', identity)
|
|
|
|
conn.del("#{identity}:workers")
|
|
|
|
end
|
2014-03-08 01:41:10 -05:00
|
|
|
end
|
2013-01-29 11:43:44 -05:00
|
|
|
end
|
2014-08-08 00:03:34 -04:00
|
|
|
|
2013-01-29 11:15:34 -05:00
|
|
|
end
|
|
|
|
end
|