mirror of
https://github.com/discourse/discourse.git
synced 2025-03-06 03:09:43 +00:00
fix initialization issues with unicorn
amend unicorn script to demonize sidekiq create a sidekiq demon that unicorn consumes correct bug in exec_sql with empty params
This commit is contained in:
parent
15de4ac890
commit
c4bab8915c
@ -11,20 +11,20 @@ Thread.new do
|
|||||||
old_time = File.ctime(file).to_i if File.exists? file
|
old_time = File.ctime(file).to_i if File.exists? file
|
||||||
wait_seconds = 4
|
wait_seconds = 4
|
||||||
|
|
||||||
return if $PROGRAM_NAME !~ /thin/
|
if $PROGRAM_NAME =~ /thin/
|
||||||
|
while true
|
||||||
|
time = File.ctime(file).to_i if File.exists? file
|
||||||
|
|
||||||
while true
|
if old_time != time
|
||||||
time = File.ctime(file).to_i if File.exists? file
|
Rails.logger.info "attempting to reload #{$$} #{$PROGRAM_NAME} in #{wait_seconds} seconds"
|
||||||
|
$shutdown = true
|
||||||
|
sleep wait_seconds
|
||||||
|
Rails.logger.info "restarting #{$$}"
|
||||||
|
Process.kill("HUP", $$)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
if old_time != time
|
sleep 1
|
||||||
Rails.logger.info "attempting to reload #{$$} #{$PROGRAM_NAME} in #{wait_seconds} seconds"
|
|
||||||
$shutdown = true
|
|
||||||
sleep wait_seconds
|
|
||||||
Rails.logger.info "restarting #{$$}"
|
|
||||||
Process.kill("HUP", $$)
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sleep 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
|
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
|
||||||
|
|
||||||
# tune down if not enough ram
|
# tune down if not enough ram
|
||||||
worker_processes 2
|
worker_processes 3
|
||||||
|
|
||||||
working_directory discourse_path
|
working_directory discourse_path
|
||||||
|
|
||||||
listen 8080, :tcp_nopush => true
|
# listen "#{discourse_path}/tmp/sockets/unicorn.sock"
|
||||||
|
listen 3000
|
||||||
|
|
||||||
# nuke workers after 30 seconds instead of 60 seconds (the default)
|
# nuke workers after 30 seconds instead of 60 seconds (the default)
|
||||||
timeout 30
|
timeout 30
|
||||||
@ -34,42 +35,26 @@ check_client_connection false
|
|||||||
|
|
||||||
initialized = false
|
initialized = false
|
||||||
before_fork do |server, worker|
|
before_fork do |server, worker|
|
||||||
|
|
||||||
unless initialized
|
unless initialized
|
||||||
# load up the yaml for the localization bits, in master process
|
# load up the yaml for the localization bits, in master process
|
||||||
I18n.t(:posts)
|
I18n.t(:posts)
|
||||||
# get rid of rubbish so we don't share it
|
# get rid of rubbish so we don't share it
|
||||||
GC.start
|
GC.start
|
||||||
|
|
||||||
|
require 'demon/sidekiq'
|
||||||
|
Demon::Sidekiq.start(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveRecord::Base.connection.disconnect!
|
ActiveRecord::Base.connection.disconnect!
|
||||||
$redis.client.disconnect
|
$redis.client.disconnect
|
||||||
|
|
||||||
|
|
||||||
#TODO
|
|
||||||
# at this point we want to fork out sidekiq, it will let us reuse the shared memory
|
|
||||||
|
|
||||||
# The following is only recommended for memory/DB-constrained
|
|
||||||
# installations. It is not needed if your system can house
|
|
||||||
# twice as many worker_processes as you have configured.
|
|
||||||
#
|
|
||||||
# # This allows a new master process to incrementally
|
|
||||||
# # phase out the old master process with SIGTTOU to avoid a
|
|
||||||
# # thundering herd (especially in the "preload_app false" case)
|
|
||||||
# # when doing a transparent upgrade. The last worker spawned
|
|
||||||
# # will then kill off the old master process with a SIGQUIT.
|
|
||||||
# old_pid = "#{server.config[:pid]}.oldbin"
|
|
||||||
# if old_pid != server.pid
|
|
||||||
# begin
|
|
||||||
# sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
|
||||||
# Process.kill(sig, File.read(old_pid).to_i)
|
|
||||||
# rescue Errno::ENOENT, Errno::ESRCH
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# Throttle the master from forking too quickly by sleeping. Due
|
# Throttle the master from forking too quickly by sleeping. Due
|
||||||
# to the implementation of standard Unix signal handlers, this
|
# to the implementation of standard Unix signal handlers, this
|
||||||
# helps (but does not completely) prevent identical, repeated signals
|
# helps (but does not completely) prevent identical, repeated signals
|
||||||
# from being lost when the receiving process is busy.
|
# from being lost when the receiving process is busy.
|
||||||
# sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
after_fork do |server, worker|
|
after_fork do |server, worker|
|
||||||
|
164
lib/demon/sidekiq.rb
Normal file
164
lib/demon/sidekiq.rb
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
module Demon; end
|
||||||
|
|
||||||
|
# intelligent fork based demonizer for sidekiq
|
||||||
|
class Demon::Base
|
||||||
|
|
||||||
|
def self.start(count)
|
||||||
|
@demons ||= {}
|
||||||
|
count.times do |i|
|
||||||
|
(@demons["#{prefix}_#{i}"] ||= new(i)).start
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.stop
|
||||||
|
@demons.values.each do |demon|
|
||||||
|
demon.stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(index)
|
||||||
|
@index = index
|
||||||
|
@pid = nil
|
||||||
|
@parent_pid = Process.pid
|
||||||
|
@monitor = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_file
|
||||||
|
"#{Rails.root}/tmp/pids/#{self.class.prefix}_#{@index}.pid"
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
if @monitor
|
||||||
|
@monitor.kill
|
||||||
|
@monitor.join
|
||||||
|
@monitor = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if @pid
|
||||||
|
Process.kill("SIGHUP",@pid)
|
||||||
|
@pid = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
if existing = already_running?
|
||||||
|
# should not happen ... so kill violently
|
||||||
|
Process.kill("SIGTERM",existing)
|
||||||
|
end
|
||||||
|
|
||||||
|
return if @pid
|
||||||
|
|
||||||
|
if @pid = fork
|
||||||
|
write_pid_file
|
||||||
|
monitor_child
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
monitor_parent
|
||||||
|
establish_app
|
||||||
|
after_fork
|
||||||
|
end
|
||||||
|
|
||||||
|
def already_running?
|
||||||
|
if File.exists? pid_file
|
||||||
|
pid = File.read(pid_file).to_i
|
||||||
|
if alive?(pid)
|
||||||
|
return pid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def monitor_child
|
||||||
|
@monitor ||= Thread.new do
|
||||||
|
while true
|
||||||
|
sleep 5
|
||||||
|
unless alive?(@pid)
|
||||||
|
STDERR.puts "#{@pid} died, restarting sidekiq"
|
||||||
|
@pid = nil
|
||||||
|
start
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_pid_file
|
||||||
|
FileUtils.mkdir_p(Rails.root + "tmp/pids")
|
||||||
|
File.open(pid_file,'w') do |f|
|
||||||
|
f.write(@pid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_pid_file
|
||||||
|
File.delete(pid_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def monitor_parent
|
||||||
|
Thread.new do
|
||||||
|
while true
|
||||||
|
exit unless alive?(@parent_pid)
|
||||||
|
sleep 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def alive?(pid)
|
||||||
|
begin
|
||||||
|
Process.getpgid(pid)
|
||||||
|
true
|
||||||
|
rescue Errno::ESRCH
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def establish_app
|
||||||
|
|
||||||
|
|
||||||
|
ActiveRecord::Base.connection_handler.clear_active_connections!
|
||||||
|
ActiveRecord::Base.establish_connection
|
||||||
|
$redis.client.reconnect
|
||||||
|
Rails.cache.reconnect
|
||||||
|
MessageBus.after_fork
|
||||||
|
|
||||||
|
Signal.trap("HUP") do
|
||||||
|
begin
|
||||||
|
delete_pid_file
|
||||||
|
ensure
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# keep stuff simple for now
|
||||||
|
$stdout.reopen("/dev/null", "w")
|
||||||
|
# $stderr.reopen("/dev/null", "w")
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_fork
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Demon::Sidekiq < Demon::Base
|
||||||
|
def self.prefix
|
||||||
|
"sidekiq"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def after_fork
|
||||||
|
require 'sidekiq/cli'
|
||||||
|
|
||||||
|
begin
|
||||||
|
cli = Sidekiq::CLI.instance
|
||||||
|
cli.parse([])
|
||||||
|
cli.run
|
||||||
|
rescue => e
|
||||||
|
STDERR.puts e.message
|
||||||
|
STDERR.puts e.backtrace.join("\n")
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -61,7 +61,11 @@ class SqlBuilder
|
|||||||
if @klass
|
if @klass
|
||||||
@klass.find_by_sql(ActiveRecord::Base.send(:sanitize_sql_array, [sql, @args]))
|
@klass.find_by_sql(ActiveRecord::Base.send(:sanitize_sql_array, [sql, @args]))
|
||||||
else
|
else
|
||||||
ActiveRecord::Base.exec_sql(sql,@args)
|
if @args == {}
|
||||||
|
ActiveRecord::Base.exec_sql(sql)
|
||||||
|
else
|
||||||
|
ActiveRecord::Base.exec_sql(sql,@args)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user