unicorn-wrangler 0.0.7 → 0.0.8
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/unicorn-wrangler +1 -1
- data/lib/unicorn/wrangler.rb +103 -87
- data/lib/unicorn/wrangler/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14daf7ce37b1e4cdc63918f515f1692df2d98288
|
4
|
+
data.tar.gz: bd3ad398853fb679a09063fe23e1fda243e1ffdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff65b1fd38f6c10e67949ed25496d3bdc78bd56b6def232bda911f3f0c55198791ae8b676046e4c6e93a7b51d416691ad15696dc673981ded7df782c30c82c2e
|
7
|
+
data.tar.gz: 4188b4cecd023e45041fcd8a19e5ff5171cea6f328314678cb72ade2e055944b9f82a95b0acdf1029a93c9feada53f9ef7ad195e611591af777eb903884e98e3
|
data/bin/unicorn-wrangler
CHANGED
data/lib/unicorn/wrangler.rb
CHANGED
@@ -1,19 +1,47 @@
|
|
1
|
-
require
|
1
|
+
require 'unicorn/wrangler/version'
|
2
|
+
require 'logger'
|
2
3
|
|
3
4
|
module Unicorn
|
4
5
|
class Wrangler
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
class << self
|
7
|
+
def logger
|
8
|
+
@logger ||= Logger.new(STDOUT)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Utils
|
13
|
+
def warn(message)
|
14
|
+
Wrangler.logger.warn(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug(message)
|
18
|
+
Thread.new do
|
19
|
+
Wrangler.logger.debug(message)
|
20
|
+
end.join
|
21
|
+
end
|
22
|
+
|
23
|
+
def trap_signals(*signals, &block)
|
24
|
+
signals.map(&:to_s).each do |signal|
|
25
|
+
trap(signal) do
|
26
|
+
debug "received #{signal} (watching #{unicorn.pid})"
|
27
|
+
block.call signal
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def wait_for(seconds, &block)
|
33
|
+
end_time = Time.now + seconds
|
34
|
+
until Time.now > end_time || block.call
|
35
|
+
sleep 0.1
|
36
|
+
end
|
37
|
+
block.call
|
38
|
+
end
|
14
39
|
end
|
15
40
|
|
16
41
|
class UnicornProcess
|
42
|
+
extend Utils
|
43
|
+
include Utils
|
44
|
+
|
17
45
|
attr_reader :pid, :pidfile
|
18
46
|
|
19
47
|
def initialize(pidfile)
|
@@ -29,30 +57,40 @@ module Unicorn
|
|
29
57
|
end
|
30
58
|
|
31
59
|
def signal(msg)
|
32
|
-
|
33
|
-
Process.kill msg, pid
|
60
|
+
debug "Sending signal #{msg} to #{pid}"
|
61
|
+
Process.kill msg.to_s, pid
|
34
62
|
end
|
35
63
|
|
36
64
|
def reload(grace_period)
|
37
|
-
signal
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
65
|
+
signal :USR2
|
66
|
+
if wait_for(grace_period) { reloaded_unicorn }
|
67
|
+
Thread.new do
|
68
|
+
sleep grace_period
|
69
|
+
terminate
|
70
|
+
end
|
42
71
|
reloaded_unicorn
|
43
72
|
else
|
44
73
|
raise "unicorn didn't reload correctly within grace period (was pid #{pid})"
|
45
74
|
end
|
46
75
|
end
|
47
76
|
|
77
|
+
def reloaded_unicorn
|
78
|
+
reloaded = UnicornProcess.from_pidfile(pidfile)
|
79
|
+
if reloaded && pid != reloaded.pid
|
80
|
+
reloaded
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
48
84
|
def launch_assassin(grace_period)
|
49
85
|
if running? && !@assassin_launched
|
50
86
|
@assassin_launched = true
|
51
|
-
|
87
|
+
debug "preparing to kill unicorn #{pid} in #{grace_period} seconds"
|
52
88
|
unless fork
|
89
|
+
$0 = "unicorn-wrangler (waiting to kill #{pid})"
|
53
90
|
File.write(assassin_pidfile, Process.pid.to_s)
|
54
91
|
|
55
|
-
|
92
|
+
trap_signals :TERM do
|
93
|
+
debug "Trapped and killed assassin"
|
56
94
|
exit
|
57
95
|
end
|
58
96
|
|
@@ -67,7 +105,9 @@ module Unicorn
|
|
67
105
|
def recall_assassin
|
68
106
|
if File.exist?(assassin_pidfile)
|
69
107
|
assassin_pid = File.read(assassin_pidfile).to_i
|
70
|
-
|
108
|
+
debug "Recalling assassin with pid #{assassin_pid}"
|
109
|
+
Process.kill 'KILL', assassin_pid
|
110
|
+
File.delete assassin_pidfile
|
71
111
|
end
|
72
112
|
rescue Errno::ESRCH
|
73
113
|
end
|
@@ -78,29 +118,15 @@ module Unicorn
|
|
78
118
|
|
79
119
|
def terminate
|
80
120
|
if running?
|
81
|
-
signal
|
121
|
+
signal :TERM
|
82
122
|
else
|
83
|
-
"Attempt to terminate #{pid} failed as process not running"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def verbose(message)
|
88
|
-
self.class.verbose(message)
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.verbose(message)
|
92
|
-
Unicorn::Wrangler.verbose(message)
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.wait_for(&block)
|
96
|
-
until block.call
|
97
|
-
sleep 0.1
|
123
|
+
warn "Attempt to terminate #{pid} failed as process not running"
|
98
124
|
end
|
99
125
|
end
|
100
126
|
|
101
127
|
def self.start(pidfile, command)
|
102
128
|
Process.spawn(command, pgroup: true)
|
103
|
-
wait_for { File.exist?(pidfile) }
|
129
|
+
wait_for(60) { File.exist?(pidfile) }
|
104
130
|
new(pidfile)
|
105
131
|
end
|
106
132
|
|
@@ -109,71 +135,61 @@ module Unicorn
|
|
109
135
|
end
|
110
136
|
end
|
111
137
|
|
112
|
-
|
113
|
-
|
138
|
+
class Main
|
139
|
+
include Utils
|
140
|
+
extend Utils
|
114
141
|
|
115
|
-
|
116
|
-
|
117
|
-
else
|
118
|
-
self.unicorn = UnicornProcess.start(pidfile, command)
|
119
|
-
sleep grace_period
|
120
|
-
end
|
142
|
+
attr_reader :command, :pidfile, :grace_period
|
143
|
+
attr_accessor :unicorn
|
121
144
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
145
|
+
def initialize(command, options = {})
|
146
|
+
@command = command
|
147
|
+
@pidfile = File.expand_path(options[:pidfile] || 'unicorn.pid')
|
148
|
+
@grace_period = options[:grace_period] || 60
|
149
|
+
Wrangler.logger.level = Logger::DEBUG if options[:verbose]
|
150
|
+
@unicorn = UnicornProcess.from_pidfile(@pidfile)
|
127
151
|
end
|
128
|
-
end
|
129
152
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
kill_unicorn_after_delay
|
134
|
-
exit
|
135
|
-
end
|
136
|
-
end
|
153
|
+
def start
|
154
|
+
$0 = 'unicorn-wrangler (starting up)'
|
155
|
+
setup_signal_handlers
|
137
156
|
|
138
|
-
|
139
|
-
|
140
|
-
|
157
|
+
if unicorn && unicorn.running?
|
158
|
+
self.unicorn = unicorn.reload(grace_period)
|
159
|
+
else
|
160
|
+
self.unicorn = UnicornProcess.start(pidfile, command)
|
161
|
+
wait_for(grace_period) { unicorn.running? }
|
162
|
+
end
|
141
163
|
|
142
|
-
def loop_while_unicorn_runs
|
143
|
-
loop do
|
144
164
|
if unicorn.running?
|
145
|
-
|
165
|
+
debug "Unicorn running on #{unicorn.pid}"
|
166
|
+
$0 = "unicorn-wrangler (monitoring #{unicorn.pid})"
|
167
|
+
loop_while_unicorn_runs
|
146
168
|
else
|
147
|
-
|
169
|
+
debug "Unable to start unicorn. Exiting."
|
148
170
|
end
|
149
171
|
end
|
150
|
-
end
|
151
172
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
verbose "received #{signal} (managing #{unicorn.pid})"
|
156
|
-
block.call signal
|
173
|
+
def setup_signal_handlers
|
174
|
+
trap_signals(:HUP) do
|
175
|
+
self.unicorn = unicorn.reload(grace_period) if unicorn
|
157
176
|
end
|
158
|
-
end
|
159
|
-
end
|
160
177
|
|
161
|
-
|
162
|
-
|
163
|
-
|
178
|
+
trap_signals(:QUIT, :INT, :TERM) do |signal|
|
179
|
+
unicorn.launch_assassin(grace_period) if unicorn
|
180
|
+
exit
|
181
|
+
end
|
164
182
|
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def kill_unicorn_after_delay
|
168
|
-
unicorn.launch_assassin(grace_period) if unicorn
|
169
|
-
end
|
170
|
-
|
171
|
-
def verbose(message)
|
172
|
-
self.class.verbose(message)
|
173
|
-
end
|
174
183
|
|
175
|
-
|
176
|
-
|
184
|
+
def loop_while_unicorn_runs
|
185
|
+
loop do
|
186
|
+
if unicorn.running?
|
187
|
+
sleep 0.1
|
188
|
+
else
|
189
|
+
exit
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
177
193
|
end
|
178
194
|
end
|
179
195
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn-wrangler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Ward
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|