uc 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/uc +13 -4
- data/lib/uc/lock.rb +18 -0
- data/lib/uc/logger.rb +13 -2
- data/lib/uc/mq_logger.rb +22 -0
- data/lib/uc/mqueue.rb +56 -38
- data/lib/uc/server.rb +41 -41
- data/lib/uc/unicorn/api.rb +60 -0
- data/lib/uc/{unicorn_config.rb → unicorn/config.rb} +14 -7
- data/lib/uc/unicorn/prestart.rb +83 -0
- data/lib/uc/unicorn/rolling_restart.rb +87 -0
- data/lib/uc/version.rb +1 -1
- metadata +8 -4
- data/lib/uc/unicorn.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59c522f2247a747ec300e7cafbd827b7700f18be
|
4
|
+
data.tar.gz: 7303d81d3893d08bed3de0856835014df3882efe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bda91add1413b1fa20739eaf23b975d45920e8dd8739fce7d2d7de97db8ba1b18d9762337ced2c796203882d2a188e29dececa291e93d1ef2df7e9a31489f03
|
7
|
+
data.tar.gz: e9764c28553b46752e4d1c0689ca93a5aed0e601c0c7d3e38a531d434ee3159e66fa12c690ebb3b8bcf41cb18960d35e8b37caaededa8898c99c525b2f1f6bc1
|
data/bin/uc
CHANGED
@@ -8,7 +8,10 @@ require 'optparse'
|
|
8
8
|
require 'uc/error'
|
9
9
|
require 'uc/version'
|
10
10
|
require 'uc/server'
|
11
|
+
require 'uc/logger'
|
12
|
+
require 'uc/lock'
|
11
13
|
|
14
|
+
logger = ::Uc::Logger.logger
|
12
15
|
options = {}
|
13
16
|
options[:rails_env] = "production"
|
14
17
|
|
@@ -38,6 +41,11 @@ opts_parser = OptionParser.new do |opts|
|
|
38
41
|
exit
|
39
42
|
end
|
40
43
|
|
44
|
+
opts.on("--debug", "Show debug messages") do
|
45
|
+
logger.level = ::Logger::DEBUG
|
46
|
+
ENV["UC_DEBUG"] = "true"
|
47
|
+
end
|
48
|
+
|
41
49
|
opts.on_tail("-h", "--help", "Show this message") do
|
42
50
|
puts opts
|
43
51
|
exit
|
@@ -46,8 +54,9 @@ end
|
|
46
54
|
|
47
55
|
begin
|
48
56
|
opts_parser.parse!(ARGV)
|
49
|
-
|
50
57
|
app_dir = options[:app_dir] || Dir.pwd
|
58
|
+
lock = ::Uc::Lock.new(app_dir)
|
59
|
+
lock.acquire
|
51
60
|
server = ::Uc::Server.new(app_dir, rails_env: options[:rails_env])
|
52
61
|
command = ARGV.shift
|
53
62
|
|
@@ -55,14 +64,14 @@ begin
|
|
55
64
|
when "start", "stop", "restart", "status"
|
56
65
|
server.send command.to_sym
|
57
66
|
when "rr", "rolling-restart"
|
58
|
-
server.rolling_restart
|
67
|
+
server.rolling_restart
|
59
68
|
when nil
|
60
|
-
|
69
|
+
logger.error "No command specified"
|
61
70
|
puts opts_parser
|
62
71
|
abort
|
63
72
|
end
|
64
73
|
|
65
74
|
rescue OptionParser::InvalidOption, OptionParser::MissingArgument, ::Uc::Error => e
|
66
|
-
|
75
|
+
logger.error "#{e.message}"
|
67
76
|
abort
|
68
77
|
end
|
data/lib/uc/lock.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'uc/error'
|
2
|
+
module Uc
|
3
|
+
class Lock
|
4
|
+
|
5
|
+
attr_reader :app_dir
|
6
|
+
def initialize(app_dir)
|
7
|
+
@app_dir = app_dir
|
8
|
+
end
|
9
|
+
|
10
|
+
def acquire
|
11
|
+
Dir.chdir app_dir do
|
12
|
+
lock_acquired = File.new("tmp/.uc.lock", "a+").flock( File::LOCK_NB | File::LOCK_EX )
|
13
|
+
raise ::Uc::Error,"another uc process is already running" if not lock_acquired
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/uc/logger.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'uc/mq_logger'
|
2
3
|
module Uc
|
3
4
|
module Logger
|
4
5
|
|
@@ -6,16 +7,26 @@ module Uc
|
|
6
7
|
@logger ||= begin
|
7
8
|
logger = ::Logger.new(STDOUT)
|
8
9
|
logger.formatter = proc do |severity, datetime, progname, msg|
|
9
|
-
"
|
10
|
+
if severity == "INFO"
|
11
|
+
"#{msg}\n"
|
12
|
+
else
|
13
|
+
"#{severity} #{msg}\n"
|
14
|
+
end
|
10
15
|
end
|
11
16
|
logger.level = ::Logger::INFO
|
12
17
|
logger
|
13
18
|
end
|
14
|
-
end
|
19
|
+
end
|
15
20
|
|
16
21
|
def logger
|
17
22
|
::Uc::Logger.logger
|
18
23
|
end
|
19
24
|
|
25
|
+
def mq_log(msg)
|
26
|
+
return if not respond_to? :queue_name
|
27
|
+
@mq_logger ||= ::Uc::MqLogger.new(queue_name)
|
28
|
+
@mq_logger.log msg
|
29
|
+
end
|
30
|
+
|
20
31
|
end
|
21
32
|
end
|
data/lib/uc/mq_logger.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Uc
|
2
|
+
class MqLogger
|
3
|
+
|
4
|
+
attr_reader :queue_name
|
5
|
+
|
6
|
+
def initialize(queue_name)
|
7
|
+
@queue_name = queue_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def mq
|
11
|
+
@mq ||= ::Uc::Mqueue.new(queue_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def log(msg)
|
15
|
+
@writer ||= mq.nb_writer
|
16
|
+
@writer.send msg
|
17
|
+
rescue Errno::ENOENT, Errno::EAGAIN, Errno::EACCES, Errno::EMSGSIZE => e
|
18
|
+
puts "#{e.class} #{e.message}"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/lib/uc/mqueue.rb
CHANGED
@@ -1,66 +1,84 @@
|
|
1
1
|
require 'posix_mq'
|
2
|
-
require 'uc/logger'
|
3
2
|
module Uc
|
4
3
|
class Mqueue
|
5
|
-
include ::Uc::Logger
|
6
4
|
|
7
|
-
attr_reader :name
|
5
|
+
attr_reader :name, :max_msg, :msg_size
|
8
6
|
|
9
|
-
def initialize(name)
|
7
|
+
def initialize(name, max_msg: 10, msg_size: 100)
|
10
8
|
@name = name
|
9
|
+
@max_msg = max_msg
|
10
|
+
@msg_size = msg_size
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
attr = ::POSIX_MQ::Attr.new(0,100,100) # o_readonly, maxmsg, msgsize
|
15
|
-
puts name
|
13
|
+
def create
|
16
14
|
::POSIX_MQ.new("/#{name}", :rw, 0700, attr)
|
17
|
-
make_empty
|
18
15
|
end
|
19
16
|
|
20
|
-
def
|
21
|
-
|
17
|
+
def recreate
|
18
|
+
destroy
|
19
|
+
create
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
return
|
22
|
+
def destroy
|
23
|
+
::POSIX_MQ.unlink("/#{name}")
|
24
|
+
rescue
|
25
|
+
return false
|
28
26
|
end
|
29
27
|
|
30
|
-
def
|
31
|
-
POSIX_MQ.new(
|
28
|
+
def attr
|
29
|
+
::POSIX_MQ::Attr.new(0,max_msg,msg_size)
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_mq(io_mode, nonblock, &block)
|
33
|
+
mq = ::POSIX_MQ.new("/#{name}", io_mode)
|
34
|
+
mq.nonblock = true if nonblock
|
35
|
+
return mq if not block_given?
|
36
|
+
|
37
|
+
begin
|
38
|
+
yield mq
|
39
|
+
ensure
|
40
|
+
mq.close if mq
|
41
|
+
end
|
32
42
|
end
|
33
43
|
|
34
|
-
def
|
35
|
-
|
36
|
-
writer.nonblock = true
|
37
|
-
return writer
|
44
|
+
def reader(&block)
|
45
|
+
new_mq(:r, false, &block)
|
38
46
|
end
|
39
47
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
def nb_reader(&block)
|
49
|
+
new_mq(:r, true, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def writer(&block)
|
53
|
+
new_mq(IO::WRONLY, false, &block)
|
45
54
|
end
|
46
55
|
|
47
|
-
def
|
56
|
+
def nb_writer(&block)
|
57
|
+
new_mq(IO::WRONLY, true, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def wait(event, timeout, output: false)
|
61
|
+
event = event.to_s
|
48
62
|
message = ""
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
reader do |r|
|
64
|
+
while message != event do
|
65
|
+
r.receive(message, timeout)
|
66
|
+
puts "> #{message}" if output
|
67
|
+
end
|
53
68
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
69
|
+
return message
|
70
|
+
end
|
71
|
+
|
72
|
+
def watch(event, timeout: 30, recreate: true, &block)
|
73
|
+
self.recreate if recreate
|
74
|
+
clear
|
75
|
+
yield
|
76
|
+
wait(event, timeout, output: true)
|
58
77
|
end
|
59
78
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
mq.receive
|
79
|
+
def clear
|
80
|
+
nb_reader do |mq|
|
81
|
+
loop { mq.receive }
|
64
82
|
end
|
65
83
|
rescue Errno::EAGAIN
|
66
84
|
return
|
data/lib/uc/server.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'uc/logger'
|
2
2
|
require 'uc/shell_helper'
|
3
3
|
require 'uc/mqueue'
|
4
|
-
require 'uc/unicorn'
|
5
|
-
require 'uc/
|
4
|
+
require 'uc/unicorn/api'
|
5
|
+
require 'uc/unicorn/config'
|
6
6
|
require 'uc/error'
|
7
7
|
|
8
8
|
module Uc
|
9
|
+
|
9
10
|
class Server
|
10
11
|
|
11
12
|
include ::Uc::ShellHelper
|
@@ -15,9 +16,9 @@ module Uc
|
|
15
16
|
attr_reader :rails_env
|
16
17
|
|
17
18
|
def initialize(app_dir, rails_env: "production")
|
18
|
-
@uconfig = ::Uc::
|
19
|
+
@uconfig = ::Uc::Unicorn::Config.new(app_dir)
|
19
20
|
@rails_env = rails_env
|
20
|
-
load_env
|
21
|
+
@uconfig.load_env
|
21
22
|
end
|
22
23
|
|
23
24
|
def app_env(&block)
|
@@ -48,21 +49,6 @@ module Uc
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
def kill(pid, timeout)
|
52
|
-
Process.kill(:TERM, pid)
|
53
|
-
logger.debug "TERM signal sent to #{pid}"
|
54
|
-
(1..timeout).each do
|
55
|
-
if not process_running? pid
|
56
|
-
logger.info "Stopped #{pid}"
|
57
|
-
return
|
58
|
-
end
|
59
|
-
sleep 1
|
60
|
-
end
|
61
|
-
Process.kill(9, pid)
|
62
|
-
sleep 1
|
63
|
-
logger.info "Killed #{pid}"
|
64
|
-
end
|
65
|
-
|
66
52
|
def status
|
67
53
|
status = ( server_running? ? "Running pid #{pid}" : "Stopped")
|
68
54
|
puts status
|
@@ -73,20 +59,44 @@ module Uc
|
|
73
59
|
start
|
74
60
|
end
|
75
61
|
|
76
|
-
def rolling_restart
|
62
|
+
def rolling_restart
|
77
63
|
app_env
|
78
64
|
if not server_running?
|
79
65
|
start
|
80
66
|
return
|
81
67
|
end
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
68
|
+
mq = ::Uc::Mqueue.new(queue_name)
|
69
|
+
begin
|
70
|
+
mq.watch :fin do
|
71
|
+
Process.kill("USR2", pid)
|
72
|
+
end
|
73
|
+
rescue Errno::EACCES
|
74
|
+
raise ::Uc::Error, "unable to setup message queue"
|
75
|
+
rescue Errno::ENOENT
|
76
|
+
raise ::Uc::Error, "message queue deleted"
|
77
|
+
rescue Errno::ETIMEDOUT
|
78
|
+
raise ::Uc::Error, "timeout reached while waiting for server to restart"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def kill(pid, timeout)
|
85
|
+
Process.kill(:TERM, pid)
|
86
|
+
logger.debug "TERM signal sent to #{pid}"
|
87
|
+
(1..timeout).each do
|
88
|
+
if not process_running? pid
|
89
|
+
logger.info "Stopped #{pid}"
|
90
|
+
return
|
91
|
+
end
|
92
|
+
sleep 1
|
87
93
|
end
|
94
|
+
Process.kill(9, pid)
|
95
|
+
sleep 1
|
96
|
+
logger.info "Killed #{pid}"
|
88
97
|
end
|
89
98
|
|
99
|
+
|
90
100
|
def process_running?(pid)
|
91
101
|
return false if pid <= 0
|
92
102
|
Process.getpgid pid
|
@@ -99,25 +109,15 @@ module Uc
|
|
99
109
|
process_running? pid
|
100
110
|
end
|
101
111
|
|
102
|
-
def get_queue_name
|
103
|
-
Dir.chdir uconfig.app_dir do
|
104
|
-
return ::Uc::Unicorn.get_queue_name
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def read_pid
|
109
|
-
uconfig.read_pid
|
110
|
-
end
|
111
|
-
|
112
112
|
def pid
|
113
|
-
|
113
|
+
uconfig.pid
|
114
114
|
end
|
115
115
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
116
|
+
def queue_name
|
117
|
+
@queue_name ||= Dir.chdir uconfig.app_dir do
|
118
|
+
api = ::Uc::Unicorn::Api.new
|
119
|
+
api.queue_name
|
120
|
+
end
|
121
121
|
end
|
122
122
|
|
123
123
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'uc/unicorn/rolling_restart'
|
2
|
+
require 'uc/unicorn/prestart'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module Uc; module Unicorn
|
6
|
+
|
7
|
+
class Api
|
8
|
+
|
9
|
+
attr_reader :run_id
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@run_id = SecureRandom.hex(3)
|
13
|
+
end
|
14
|
+
|
15
|
+
def rolling_restart(server, worker, **kwargs)
|
16
|
+
rolling_restart = ::Uc::Unicorn::RollingRestart.new(server, worker, queue_name, **kwargs)
|
17
|
+
rolling_restart.run_id = @run_id
|
18
|
+
rolling_restart.run
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def prestart(server, worker, **kwargs)
|
23
|
+
prestart = ::Uc::Unicorn::Prestart.new(server, worker, queue_name, **kwargs)
|
24
|
+
prestart.run_id = @run_id
|
25
|
+
prestart.run
|
26
|
+
end
|
27
|
+
|
28
|
+
def clean_env
|
29
|
+
ENV.delete "BUNDLE_BIN_PATH"
|
30
|
+
ENV.delete "RUBYLIB"
|
31
|
+
ENV.delete "RUBYOPT"
|
32
|
+
ENV.delete "GEM_HOME"
|
33
|
+
ENV.delete "GEM_PATH"
|
34
|
+
end
|
35
|
+
|
36
|
+
def queue_name
|
37
|
+
@queue_name ||= begin
|
38
|
+
queue_name_from_file || "unicorn_#{Process.uid}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def queue_name_from_file
|
45
|
+
queue_file = Pathname.new queue_name_file
|
46
|
+
queue_name = nil
|
47
|
+
if queue_file.readable?
|
48
|
+
queue_name = File.read(queue_file).chomp
|
49
|
+
queue_name = (queue_name.empty? ? nil : queue_name)
|
50
|
+
end
|
51
|
+
return queue_name
|
52
|
+
end
|
53
|
+
|
54
|
+
def queue_name_file
|
55
|
+
"config/unicorn_mq"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end; end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'uc/logger'
|
3
|
-
module Uc
|
4
|
-
class
|
3
|
+
module Uc; module Unicorn
|
4
|
+
class Config
|
5
5
|
|
6
6
|
include ::Uc::Logger
|
7
7
|
|
@@ -43,6 +43,10 @@ module Uc
|
|
43
43
|
return -1
|
44
44
|
end
|
45
45
|
|
46
|
+
def pid
|
47
|
+
@pid ||= read_pid
|
48
|
+
end
|
49
|
+
|
46
50
|
def check_dirs
|
47
51
|
logger.debug "Using app_dir => #{app_dir}"
|
48
52
|
raise ::Uc::Error, %{app_dir not readable} if not path_readable? app_dir
|
@@ -57,6 +61,12 @@ module Uc
|
|
57
61
|
@dirs_checked
|
58
62
|
end
|
59
63
|
|
64
|
+
def load_env
|
65
|
+
env_file = rpath "config/uc_env.rb"
|
66
|
+
File.readable? env_file and
|
67
|
+
load env_file
|
68
|
+
rescue LoadError
|
69
|
+
end
|
60
70
|
|
61
71
|
private
|
62
72
|
|
@@ -66,14 +76,11 @@ module Uc
|
|
66
76
|
"#{app_dir}/#{path}"
|
67
77
|
end
|
68
78
|
|
69
|
-
def rpathname(path)
|
70
|
-
Pathname.new(rpath(path))
|
71
|
-
end
|
72
|
-
|
73
79
|
def path_readable?(path_str)
|
74
80
|
path = Pathname.new(path_str)
|
75
81
|
path.readable?
|
76
82
|
end
|
77
83
|
|
84
|
+
|
78
85
|
end
|
79
|
-
end
|
86
|
+
end; end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'uc/logger'
|
2
|
+
require 'uc/mqueue'
|
3
|
+
|
4
|
+
module Uc; module Unicorn;
|
5
|
+
class Prestart
|
6
|
+
|
7
|
+
include ::Uc::Logger
|
8
|
+
|
9
|
+
attr_reader :server, :worker, :queue_name, :url
|
10
|
+
attr_accessor :run_id
|
11
|
+
|
12
|
+
def initialize(server, worker, queue_name, url: "/", run_id: nil)
|
13
|
+
@server = server
|
14
|
+
@worker = worker
|
15
|
+
@url = url
|
16
|
+
@queue_name = queue_name
|
17
|
+
@run_id = run_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def app
|
21
|
+
@app ||= server.instance_variable_get("@app")
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
response = app.call(rack_request)
|
26
|
+
body = response[2]
|
27
|
+
body.close
|
28
|
+
end_prestart
|
29
|
+
rescue => e
|
30
|
+
logger.warn "pre start failed for worker : #{e.message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def worker_id
|
37
|
+
worker.nr + 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def rack_request
|
41
|
+
Rack::MockRequest.env_for("http://127.0.0.1/#{url}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def last_worker?
|
45
|
+
(worker.nr + 1) == server.worker_processes
|
46
|
+
end
|
47
|
+
|
48
|
+
def end_prestart
|
49
|
+
if last_worker?
|
50
|
+
logger.debug "[ps] no_event #{worker_id}"
|
51
|
+
return
|
52
|
+
end
|
53
|
+
logger.debug "[ps] start #{worker_id}"
|
54
|
+
send_prestart_end
|
55
|
+
mq_log "prestart end worker #{worker_id}"
|
56
|
+
logger.debug "[ps] end #{worker_id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def send_prestart_end
|
60
|
+
mq.create
|
61
|
+
mq.clear
|
62
|
+
mq.nb_writer do |writer|
|
63
|
+
writer.send prestart_end_event
|
64
|
+
end
|
65
|
+
rescue Errno::ENOENT, Errno::EAGAIN, Errno::EACCES => e
|
66
|
+
logger.warn "prestart failed for worker #{worker.nr + 1}: #{e.class}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def prestart_end_event
|
70
|
+
run_id ? "prestart_end_#{run_id}" : "prestart_end"
|
71
|
+
end
|
72
|
+
|
73
|
+
def mq
|
74
|
+
@mq ||= ::Uc::Mqueue.new(prestart_queue_name, max_msg: 10, msg_size: 30)
|
75
|
+
end
|
76
|
+
|
77
|
+
def prestart_queue_name
|
78
|
+
"#{queue_name}_prestart_#{worker.nr}"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end; end
|
83
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'uc/mqueue'
|
2
|
+
require 'uc/logger'
|
3
|
+
module Uc; module Unicorn
|
4
|
+
class RollingRestart
|
5
|
+
|
6
|
+
include ::Uc::Logger
|
7
|
+
attr_reader :server, :worker, :queue_name, :prestart_wait, :sleep_secs
|
8
|
+
attr_accessor :run_id
|
9
|
+
|
10
|
+
def initialize(server, worker, queue_name, prestart_wait: nil, sleep_secs: 0.1)
|
11
|
+
@server = server
|
12
|
+
@worker = worker
|
13
|
+
@queue_name = queue_name
|
14
|
+
@prestart_wait = prestart_wait
|
15
|
+
@sleep_secs = sleep_secs
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
return if not (server && worker)
|
20
|
+
return if not restart?
|
21
|
+
|
22
|
+
destroy_prestart_queues
|
23
|
+
wait_for_prestart_end_event
|
24
|
+
sleep sleep_secs if not first_worker?
|
25
|
+
kill_old_worker
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def prestart_mq
|
31
|
+
@prestart_mq ||= ::Uc::Mqueue.new(prestart_queue, max_msg: 10, msg_size: 30)
|
32
|
+
end
|
33
|
+
|
34
|
+
def destroy_prestart_queues
|
35
|
+
return if not first_worker?
|
36
|
+
(0..server.worker_processes).each do |i|
|
37
|
+
mq = ::Uc::Mqueue.new("#{queue_name}_prestart_#{i}")
|
38
|
+
mq.destroy
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def prestart_queue
|
43
|
+
first_worker? ? nil : "#{queue_name}_prestart_#{worker.nr - 1}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def wait_for_prestart_end_event
|
47
|
+
return if not prestart_wait
|
48
|
+
if not prestart_queue
|
49
|
+
logger.debug "[rr] no ps wait for #{worker.nr + 1}"
|
50
|
+
return
|
51
|
+
end
|
52
|
+
begin
|
53
|
+
prestart_mq.create
|
54
|
+
msg = prestart_mq.wait( prestart_end_event, prestart_wait)
|
55
|
+
logger.debug "[rr] ps end event #{prestart_end_event} for #{ worker.nr + 1}"
|
56
|
+
rescue => e
|
57
|
+
logger.info "#{e.class} #{e.message}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def kill_old_worker
|
62
|
+
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
63
|
+
Process.kill(sig, File.read(old_pid).to_i)
|
64
|
+
mq_log "starting worker #{worker.nr + 1}"
|
65
|
+
mq_log "fin" if sig == :QUIT
|
66
|
+
rescue Errno::ENOENT, Errno::ESRCH, Errno::EAGAIN, Errno::EACCES => e
|
67
|
+
logger.error "rolling restart #{e.class} #{e.message}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def prestart_end_event
|
71
|
+
run_id ? "prestart_end_#{run_id}" : "prestart_end"
|
72
|
+
end
|
73
|
+
|
74
|
+
def restart?
|
75
|
+
old_pid != server.pid
|
76
|
+
end
|
77
|
+
|
78
|
+
def first_worker?
|
79
|
+
worker.nr == 0
|
80
|
+
end
|
81
|
+
|
82
|
+
def old_pid
|
83
|
+
"#{server.config[:pid]}.oldbin"
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end; end
|
data/lib/uc/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neeraj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -68,12 +68,16 @@ files:
|
|
68
68
|
- bin/uc
|
69
69
|
- lib/uc.rb
|
70
70
|
- lib/uc/error.rb
|
71
|
+
- lib/uc/lock.rb
|
71
72
|
- lib/uc/logger.rb
|
73
|
+
- lib/uc/mq_logger.rb
|
72
74
|
- lib/uc/mqueue.rb
|
73
75
|
- lib/uc/server.rb
|
74
76
|
- lib/uc/shell_helper.rb
|
75
|
-
- lib/uc/unicorn.rb
|
76
|
-
- lib/uc/
|
77
|
+
- lib/uc/unicorn/api.rb
|
78
|
+
- lib/uc/unicorn/config.rb
|
79
|
+
- lib/uc/unicorn/prestart.rb
|
80
|
+
- lib/uc/unicorn/rolling_restart.rb
|
77
81
|
- lib/uc/version.rb
|
78
82
|
- uc.gemspec
|
79
83
|
homepage: ''
|
data/lib/uc/unicorn.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require 'uc/mqueue'
|
2
|
-
module Uc
|
3
|
-
module Unicorn
|
4
|
-
|
5
|
-
def self.queue_file
|
6
|
-
"config/unicorn_mq"
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.rolling_restart(server, worker, queue_name: nil, sleep_secs: 1)
|
10
|
-
queue_name ||= get_queue_name
|
11
|
-
old_pid = "#{server.config[:pid]}.oldbin"
|
12
|
-
if old_pid != server.pid
|
13
|
-
sleep sleep_secs
|
14
|
-
begin
|
15
|
-
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
16
|
-
Process.kill(sig, File.read(old_pid).to_i)
|
17
|
-
|
18
|
-
mq = ::Uc::Mqueue.new(queue_name)
|
19
|
-
writer = mq.nb_writer
|
20
|
-
writer.send("started worker #{worker.nr + 1}")
|
21
|
-
if sig == :QUIT
|
22
|
-
writer.send("fin")
|
23
|
-
end
|
24
|
-
rescue Errno::ENOENT, Errno::ESRCH, Errno::EAGAIN => e
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.clean_env
|
30
|
-
ENV.delete "BUNDLE_BIN_PATH"
|
31
|
-
ENV.delete "RUBYLIB"
|
32
|
-
ENV.delete "RUBYOPT"
|
33
|
-
ENV.delete "GEM_HOME"
|
34
|
-
ENV.delete "GEM_PATH"
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
def self.get_queue_name
|
39
|
-
queue_name = queue_name_from_file
|
40
|
-
queue_name ||= "unicorn_#{Process.uid}"
|
41
|
-
return queue_name
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.queue_name_from_file
|
45
|
-
queue_file = Pathname.new self.queue_file
|
46
|
-
queue_name = nil
|
47
|
-
if queue_file.readable?
|
48
|
-
queue_name = File.read(queue_file).chomp
|
49
|
-
queue_name = (queue_name.empty? ? nil : queue_name)
|
50
|
-
end
|
51
|
-
return queue_name
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.pre_start(server, worker, url: "/")
|
55
|
-
app = server.instance_variable_get("@app")
|
56
|
-
response = app.call(rack_request(url))
|
57
|
-
body = response[2]
|
58
|
-
body.close
|
59
|
-
rescue => e
|
60
|
-
puts "WARN: pre start url failed : #{e.message}"
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def self.rack_request(url)
|
66
|
-
Rack::MockRequest.env_for("http://127.0.0.1/#{url}")
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|