mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 12:57:29 +08: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
|
||||
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
|
||||
time = File.ctime(file).to_i if File.exists? file
|
||||
if old_time != time
|
||||
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
|
||||
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
|
||||
sleep 1
|
||||
end
|
||||
|
||||
sleep 1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
|
||||
|
||||
# tune down if not enough ram
|
||||
worker_processes 2
|
||||
worker_processes 3
|
||||
|
||||
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)
|
||||
timeout 30
|
||||
|
@ -34,42 +35,26 @@ check_client_connection false
|
|||
|
||||
initialized = false
|
||||
before_fork do |server, worker|
|
||||
|
||||
unless initialized
|
||||
# load up the yaml for the localization bits, in master process
|
||||
I18n.t(:posts)
|
||||
# get rid of rubbish so we don't share it
|
||||
GC.start
|
||||
|
||||
require 'demon/sidekiq'
|
||||
Demon::Sidekiq.start(1)
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.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
|
||||
# to the implementation of standard Unix signal handlers, this
|
||||
# helps (but does not completely) prevent identical, repeated signals
|
||||
# from being lost when the receiving process is busy.
|
||||
# sleep 1
|
||||
sleep 1
|
||||
end
|
||||
|
||||
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
|
||||
@klass.find_by_sql(ActiveRecord::Base.send(:sanitize_sql_array, [sql, @args]))
|
||||
else
|
||||
ActiveRecord::Base.exec_sql(sql,@args)
|
||||
if @args == {}
|
||||
ActiveRecord::Base.exec_sql(sql)
|
||||
else
|
||||
ActiveRecord::Base.exec_sql(sql,@args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user