uc 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|