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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 467ba192f3c2102dbc67f8fa957081576ca2e1a0
4
- data.tar.gz: 0e3fc78a240edc9c0c0982d60dc2579ecffff3a6
3
+ metadata.gz: 14daf7ce37b1e4cdc63918f515f1692df2d98288
4
+ data.tar.gz: bd3ad398853fb679a09063fe23e1fda243e1ffdb
5
5
  SHA512:
6
- metadata.gz: 5e7eebda41d84eb9a914a93ad9d8914591963877d8cc5d51c9d42b0e838f026e763317b8db0deccc9b316a5c5cbb3176ea9a2c72137ea5a9af02e7ee808d7c24
7
- data.tar.gz: 428f1680fea401c017cc88f6371457bcdf24cbd8dc2a14ad6035faa5adfd561cdfe7dc1317af53ea178f47864854325f7213421b97fceeebb1a5eb93a2c2e304
6
+ metadata.gz: ff65b1fd38f6c10e67949ed25496d3bdc78bd56b6def232bda911f3f0c55198791ae8b676046e4c6e93a7b51d416691ad15696dc673981ded7df782c30c82c2e
7
+ data.tar.gz: 4188b4cecd023e45041fcd8a19e5ff5171cea6f328314678cb72ade2e055944b9f82a95b0acdf1029a93c9feada53f9ef7ad195e611591af777eb903884e98e3
@@ -22,5 +22,5 @@ OptionParser.new do |opts|
22
22
  end
23
23
  end.parse!(ARGV[0...command_index])
24
24
 
25
- launcher = Unicorn::Wrangler.new command, options
25
+ launcher = Unicorn::Wrangler::Main.new command, options
26
26
  launcher.start
@@ -1,19 +1,47 @@
1
- require "unicorn/wrangler/version"
1
+ require 'unicorn/wrangler/version'
2
+ require 'logger'
2
3
 
3
4
  module Unicorn
4
5
  class Wrangler
5
- attr_reader :command, :pidfile, :grace_period
6
- attr_accessor :unicorn
7
-
8
- def initialize(command, options = {})
9
- @command = command
10
- @pidfile = File.expand_path(options[:pidfile] || 'unicorn.pid')
11
- @grace_period = options[:grace_period] || 60
12
- @verbose = options[:verbose]
13
- @unicorn = UnicornProcess.from_pidfile(@pidfile)
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
- puts "Sending signal #{msg} to #{pid}"
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 "USR2"
38
- sleep grace_period
39
- reloaded_unicorn = UnicornProcess.from_pidfile(pidfile)
40
- if reloaded_unicorn && pid != reloaded_unicorn.pid
41
- terminate
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
- puts "preparing to kill unicorn #{pid} in #{grace_period} seconds"
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
- trap 'TERM' do
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
- Process.kill 'TERM', assassin_pid
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 'TERM'
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
- def start
113
- setup_signal_handlers
138
+ class Main
139
+ include Utils
140
+ extend Utils
114
141
 
115
- if unicorn && unicorn.running?
116
- self.unicorn = reload_unicorn
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
- if unicorn.running?
123
- verbose "Unicorn running on #{unicorn.pid}"
124
- loop_while_unicorn_runs
125
- else
126
- verbose "Unable to start unicorn. Exiting."
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
- def setup_signal_handlers
131
- trap_signals(:HUP) { reload_unicorn }
132
- trap_signals(:QUIT, :INT, :TERM) do |signal|
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
- def reload_unicorn
139
- self.unicorn = unicorn.reload(grace_period) if unicorn
140
- end
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
- sleep 0.1
165
+ debug "Unicorn running on #{unicorn.pid}"
166
+ $0 = "unicorn-wrangler (monitoring #{unicorn.pid})"
167
+ loop_while_unicorn_runs
146
168
  else
147
- exit
169
+ debug "Unable to start unicorn. Exiting."
148
170
  end
149
171
  end
150
- end
151
172
 
152
- def trap_signals(*signals, &block)
153
- signals.map(&:to_s).each do |signal|
154
- trap(signal) do
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
- def wait_for(&block)
162
- until block.call
163
- sleep 0.1
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
- def self.verbose(message)
176
- puts message if @verbose
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
@@ -1,5 +1,5 @@
1
1
  module Unicorn
2
2
  class Wrangler
3
- VERSION = "0.0.7"
3
+ VERSION = "0.0.8"
4
4
  end
5
5
  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.7
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-20 00:00:00.000000000 Z
11
+ date: 2013-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler