2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2019-10-02 00:54:08 -04:00
|
|
|
require "demon/base"
|
2013-10-09 22:33:52 -04:00
|
|
|
|
2019-10-02 00:54:08 -04:00
|
|
|
class Demon::Sidekiq < ::Demon::Base
|
2024-12-17 23:48:50 -05:00
|
|
|
HOSTNAME = Socket.gethostname
|
|
|
|
|
2013-10-09 22:33:52 -04:00
|
|
|
def self.prefix
|
|
|
|
"sidekiq"
|
|
|
|
end
|
|
|
|
|
FEATURE: set UNICORN_STATS_SOCKET_DIR for status socket
eg:
sam@ubuntu stats_sockets % socat - UNIX-CONNECT:9622.sock
gc_stat
{"count":46,"heap_allocated_pages":2459,"heap_sorted_length":2460,"heap_allocatable_pages":0,"heap_available_slots":1002267,"heap_live_slots":647293,"heap_free_slots":354974,"heap_final_slots":0,"heap_marked_slots":503494,"heap_swept_slots":498773,"heap_eden_pages":2459,"heap_tomb_pages":0,"total_allocated_pages":2459,"total_freed_pages":0,"total_allocated_objects":4337014,"total_freed_objects":3689721,"malloc_increase_bytes":6448248,"malloc_increase_bytes_limit":29188387,"minor_gc_count":36,"major_gc_count":10,"remembered_wb_unprotected_objects":19958,"remembered_wb_unprotected_objects_limit":39842,"old_objects":462019,"old_objects_limit":895782,"oldmalloc_increase_bytes":6448696,"oldmalloc_increase_bytes_limit":19350882}
2017-04-21 11:36:51 -04:00
|
|
|
def self.after_fork(&blk)
|
|
|
|
blk ? (@blk = blk) : @blk
|
|
|
|
end
|
|
|
|
|
2024-12-17 23:48:50 -05:00
|
|
|
# By default Sidekiq does a heartbeat check every 5 seconds. If the processes misses 20 heartbeat checks, we consider it
|
|
|
|
# dead and kill the process.
|
|
|
|
SIDEKIQ_HEARTBEAT_CHECK_MISS_THRESHOLD_SECONDS = 5.seconds * 20
|
|
|
|
|
|
|
|
def self.heartbeat_check
|
|
|
|
sidekiq_processes_for_current_hostname = {}
|
|
|
|
|
|
|
|
Sidekiq::ProcessSet.new.each do |process|
|
|
|
|
if process["hostname"] == HOSTNAME
|
|
|
|
sidekiq_processes_for_current_hostname[process["pid"]] = process
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
Demon::Sidekiq.demons.values.each do |daemon|
|
|
|
|
next if !daemon.already_running?
|
|
|
|
|
|
|
|
running_sidekiq_process = sidekiq_processes_for_current_hostname[daemon.pid]
|
|
|
|
|
|
|
|
if !running_sidekiq_process ||
|
|
|
|
(Time.now.to_i - running_sidekiq_process["beat"]) >
|
|
|
|
SIDEKIQ_HEARTBEAT_CHECK_MISS_THRESHOLD_SECONDS
|
|
|
|
Rails.logger.warn("Sidekiq heartbeat test failed for #{daemon.pid}, restarting")
|
|
|
|
daemon.restart
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
SIDEKIQ_RSS_MEMORY_CHECK_INTERVAL_SECONDS = 30.minutes
|
|
|
|
|
|
|
|
def self.rss_memory_check
|
|
|
|
if defined?(@@last_sidekiq_rss_memory_check) && @@last_sidekiq_rss_memory_check &&
|
|
|
|
@@last_sidekiq_rss_memory_check > Time.now.to_i - SIDEKIQ_RSS_MEMORY_CHECK_INTERVAL_SECONDS
|
|
|
|
return @@last_sidekiq_rss_memory_check
|
|
|
|
end
|
|
|
|
|
|
|
|
Demon::Sidekiq.demons.values.each do |daemon|
|
|
|
|
next if !daemon.already_running?
|
|
|
|
|
|
|
|
daemon_rss_bytes = (`ps -o rss= -p #{daemon.pid}`.chomp.to_i || 0) * 1024
|
|
|
|
|
|
|
|
if daemon_rss_bytes > max_allowed_sidekiq_rss_bytes
|
|
|
|
Rails.logger.warn(
|
|
|
|
"Sidekiq is consuming too much memory (using: %0.2fM) for '%s', restarting" %
|
|
|
|
[(daemon_rss_bytes.to_f / 1.megabyte), HOSTNAME],
|
|
|
|
)
|
|
|
|
|
|
|
|
daemon.restart
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@@last_sidekiq_rss_memory_check = Time.now.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
DEFAULT_MAX_ALLOWED_SIDEKIQ_RSS_MEGABYTES = 500
|
|
|
|
|
|
|
|
def self.max_allowed_sidekiq_rss_bytes
|
|
|
|
[ENV["UNICORN_SIDEKIQ_MAX_RSS"].to_i, DEFAULT_MAX_ALLOWED_SIDEKIQ_RSS_MEGABYTES].max.megabytes
|
|
|
|
end
|
|
|
|
|
2013-10-09 22:33:52 -04:00
|
|
|
private
|
|
|
|
|
2014-04-17 01:57:17 -04:00
|
|
|
def suppress_stdout
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
def suppress_stderr
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2024-06-03 00:51:12 -04:00
|
|
|
def log_in_trap(message, level: :info)
|
|
|
|
SignalTrapLogger.instance.log(@logger, message, level: level)
|
2024-05-28 23:15:20 -04:00
|
|
|
end
|
|
|
|
|
2013-10-09 22:33:52 -04:00
|
|
|
def after_fork
|
FEATURE: set UNICORN_STATS_SOCKET_DIR for status socket
eg:
sam@ubuntu stats_sockets % socat - UNIX-CONNECT:9622.sock
gc_stat
{"count":46,"heap_allocated_pages":2459,"heap_sorted_length":2460,"heap_allocatable_pages":0,"heap_available_slots":1002267,"heap_live_slots":647293,"heap_free_slots":354974,"heap_final_slots":0,"heap_marked_slots":503494,"heap_swept_slots":498773,"heap_eden_pages":2459,"heap_tomb_pages":0,"total_allocated_pages":2459,"total_freed_pages":0,"total_allocated_objects":4337014,"total_freed_objects":3689721,"malloc_increase_bytes":6448248,"malloc_increase_bytes_limit":29188387,"minor_gc_count":36,"major_gc_count":10,"remembered_wb_unprotected_objects":19958,"remembered_wb_unprotected_objects_limit":39842,"old_objects":462019,"old_objects_limit":895782,"oldmalloc_increase_bytes":6448696,"oldmalloc_increase_bytes_limit":19350882}
2017-04-21 11:36:51 -04:00
|
|
|
Demon::Sidekiq.after_fork&.call
|
2024-06-03 00:51:12 -04:00
|
|
|
SignalTrapLogger.instance.after_fork
|
FEATURE: set UNICORN_STATS_SOCKET_DIR for status socket
eg:
sam@ubuntu stats_sockets % socat - UNIX-CONNECT:9622.sock
gc_stat
{"count":46,"heap_allocated_pages":2459,"heap_sorted_length":2460,"heap_allocatable_pages":0,"heap_available_slots":1002267,"heap_live_slots":647293,"heap_free_slots":354974,"heap_final_slots":0,"heap_marked_slots":503494,"heap_swept_slots":498773,"heap_eden_pages":2459,"heap_tomb_pages":0,"total_allocated_pages":2459,"total_freed_pages":0,"total_allocated_objects":4337014,"total_freed_objects":3689721,"malloc_increase_bytes":6448248,"malloc_increase_bytes_limit":29188387,"minor_gc_count":36,"major_gc_count":10,"remembered_wb_unprotected_objects":19958,"remembered_wb_unprotected_objects_limit":39842,"old_objects":462019,"old_objects_limit":895782,"oldmalloc_increase_bytes":6448696,"oldmalloc_increase_bytes_limit":19350882}
2017-04-21 11:36:51 -04:00
|
|
|
|
2024-05-28 23:15:20 -04:00
|
|
|
log("Loading Sidekiq in process id #{Process.pid}")
|
2013-10-09 22:33:52 -04:00
|
|
|
require "sidekiq/cli"
|
2013-11-01 18:57:50 -04:00
|
|
|
cli = Sidekiq::CLI.instance
|
2014-04-17 01:57:17 -04:00
|
|
|
|
2020-04-16 07:13:13 -04:00
|
|
|
# Unicorn uses USR1 to indicate that log files have been rotated
|
2024-10-09 20:01:40 -04:00
|
|
|
Signal.trap("USR1") { reopen_logs }
|
|
|
|
|
|
|
|
Signal.trap("USR2") do
|
|
|
|
sleep 1
|
|
|
|
reopen_logs
|
2020-04-16 07:13:13 -04:00
|
|
|
end
|
|
|
|
|
2017-04-27 03:28:23 -04:00
|
|
|
options = ["-c", GlobalSetting.sidekiq_workers.to_s]
|
|
|
|
|
2019-08-30 06:26:16 -04:00
|
|
|
[["critical", 8], ["default", 4], ["low", 2], ["ultra_low", 1]].each do |queue_name, weight|
|
2017-04-27 03:28:23 -04:00
|
|
|
custom_queue_hostname = ENV["UNICORN_SIDEKIQ_#{queue_name.upcase}_QUEUE_HOSTNAME"]
|
|
|
|
|
2020-02-17 23:11:30 -05:00
|
|
|
if !custom_queue_hostname || custom_queue_hostname.split(",").include?(Discourse.os_hostname)
|
2017-04-27 03:28:23 -04:00
|
|
|
options << "-q"
|
|
|
|
options << "#{queue_name},#{weight}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-01-08 17:29:14 -05:00
|
|
|
# Sidekiq not as high priority as web, in this environment it is forked so a web is very
|
|
|
|
# likely running
|
|
|
|
Discourse::Utils.execute_command("renice", "-n", "5", "-p", Process.pid.to_s)
|
|
|
|
|
2017-04-27 03:28:23 -04:00
|
|
|
cli.parse(options)
|
2015-12-08 19:48:41 -05:00
|
|
|
load Rails.root + "config/initializers/100-sidekiq.rb"
|
2013-11-01 18:57:50 -04:00
|
|
|
cli.run
|
2024-06-11 00:29:48 -04:00
|
|
|
rescue => error
|
|
|
|
log(
|
|
|
|
"Error encountered while starting Sidekiq: [#{error.class}] #{error.message}\n#{error.backtrace.join("\n")}",
|
|
|
|
level: :error,
|
|
|
|
)
|
|
|
|
|
2013-11-01 18:57:50 -04:00
|
|
|
exit 1
|
2013-10-09 22:33:52 -04:00
|
|
|
end
|
2024-10-09 20:01:40 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def reopen_logs
|
|
|
|
begin
|
|
|
|
log_in_trap("Sidekiq reopening logs...")
|
|
|
|
Unicorn::Util.reopen_logs
|
|
|
|
log_in_trap("Sidekiq done reopening logs...")
|
|
|
|
rescue => error
|
|
|
|
log_in_trap(
|
|
|
|
"Error encountered while reopening logs: [#{error.class}] #{error.message}\n#{error.backtrace.join("\n")}",
|
|
|
|
level: :error,
|
|
|
|
)
|
|
|
|
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
end
|
2013-10-09 22:33:52 -04:00
|
|
|
end
|