unicorn-wrangler 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +7 -0
- data/Rakefile +1 -0
- data/bin/unicorn-wrangler +22 -0
- data/lib/unicorn/wrangler.rb +63 -0
- data/lib/unicorn/wrangler/version.rb +5 -0
- data/spec/lib/unicorn/wrangler_spec.rb +129 -0
- data/spec/support/config.ru +4 -0
- data/spec/support/unicorn.conf.rb +1 -0
- data/unicorn-wrangler.gemspec +26 -0
- metadata +130 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 1caba80d14d2ba78c0141579ee032bc2ac1f19d7
|
|
4
|
+
data.tar.gz: b3ee0aa920698aa8225e2d5795e71240b64490b4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 06a6ac39aa156fc2dded7cfd895fff7870a6ecdc98dbf8170df767c455a735e6f654b60ec5796e2302fabc9b8420047a90935578d6b2be711b1741b84c14d50e
|
|
7
|
+
data.tar.gz: d60b7bb9fdb697cf39d778deeb9749ce78e61c84f4982db231354a975680f528531a126e81791937e4af934852cfe829f884176b2c2a623e6c551ce4660a420a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Tom Ward
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Unicorn::Wrangler
|
|
2
|
+
|
|
3
|
+
A simple process to launch and relaunch unicorn. When launched, it either starts a new unicorn if none is running (found using the given pidfile), or restarts the existing unicorn if one is found.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
|
|
7
|
+
unicorn-wrangler --pidfile /path/to/unicorn.pid --startup-time 60 -- /path/to/unicorn <unicorn-options>
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'unicorn/wrangler'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
options = {}
|
|
7
|
+
|
|
8
|
+
command_index = ARGV.index("--")
|
|
9
|
+
command = ARGV[command_index + 1..-1].join(" ")
|
|
10
|
+
|
|
11
|
+
OptionParser.new do |opts|
|
|
12
|
+
opts.on("-p", "--pidfile PIDFILE", "Path to the main unicorn PIDFILE") do |pidfile|
|
|
13
|
+
options[:pidfile] = pidfile
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
opts.on("-s", "--startup-time STARTUP", "Time to wait for server to start") do |time|
|
|
17
|
+
options[:startup] = time.to_i
|
|
18
|
+
end
|
|
19
|
+
end.parse!(ARGV[0...command_index])
|
|
20
|
+
|
|
21
|
+
launcher = Unicorn::Wrangler.new command, options
|
|
22
|
+
launcher.start
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require "unicorn/wrangler/version"
|
|
2
|
+
|
|
3
|
+
module Unicorn
|
|
4
|
+
class Wrangler
|
|
5
|
+
attr_reader :command, :pidfile, :startup_period, :tick_period, :verbose
|
|
6
|
+
|
|
7
|
+
def initialize(command, options = {})
|
|
8
|
+
@command = command
|
|
9
|
+
@pidfile = File.expand_path(options[:pidfile] || 'unicorn.pid')
|
|
10
|
+
@startup_period = options[:startup] || 60
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start
|
|
14
|
+
trap_signals(:QUIT, :INT, :TERM) { exit }
|
|
15
|
+
|
|
16
|
+
if unicorn_running?
|
|
17
|
+
restart_unicorn
|
|
18
|
+
else
|
|
19
|
+
Process.spawn(command)
|
|
20
|
+
wait_for { unicorn_running? }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
loop do
|
|
24
|
+
exit unless unicorn_running?
|
|
25
|
+
sleep 1
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def trap_signals(*signals, &block)
|
|
32
|
+
signals.map(&:to_s).each do |signal|
|
|
33
|
+
trap(signal) do
|
|
34
|
+
block.call signal
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def restart_unicorn
|
|
40
|
+
original_pid = unicorn_pid
|
|
41
|
+
Process.kill "USR2", unicorn_pid
|
|
42
|
+
wait_for { unicorn_pid != original_pid }
|
|
43
|
+
sleep startup_period
|
|
44
|
+
Process.kill "TERM", original_pid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def unicorn_pid
|
|
48
|
+
File.exist?(pidfile) && File.read(pidfile).to_i
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def unicorn_running?
|
|
52
|
+
unicorn_pid && Process.getpgid(unicorn_pid)
|
|
53
|
+
rescue Errno::ESRCH
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def wait_for(&block)
|
|
58
|
+
until block.call
|
|
59
|
+
sleep 0.1
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require 'curl'
|
|
2
|
+
|
|
3
|
+
describe Unicorn::Wrangler do
|
|
4
|
+
def wrangler_path
|
|
5
|
+
Bundler.bin_path + 'unicorn-wrangler'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def unicorn_path
|
|
9
|
+
Bundler.bin_path + 'unicorn'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def unicorn_cmd
|
|
13
|
+
"#{unicorn_path} -p 7516 -c spec/support/unicorn.conf.rb spec/support/config.ru"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start_unicorn
|
|
17
|
+
Process.spawn unicorn_cmd
|
|
18
|
+
sleep 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def start_wrangler
|
|
22
|
+
@wrangler_pid = Process.spawn "#{wrangler_path} --startup-time 1 -p spec/support/unicorn.pid -- #{unicorn_cmd}"
|
|
23
|
+
sleep 1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def unicorn_pid
|
|
27
|
+
File.exist?('spec/support/unicorn.pid') && File.read('spec/support/unicorn.pid').to_i
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def unicorn_running?
|
|
31
|
+
unicorn_pid && Process.getpgid(unicorn_pid)
|
|
32
|
+
rescue Errno::ESRCH
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def wrangler_running?
|
|
37
|
+
@wrangler_pid && Process.getpgid(@wrangler_pid)
|
|
38
|
+
rescue Errno::ESRCH
|
|
39
|
+
false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def cleanup_processes
|
|
43
|
+
`kill -TERM #{unicorn_pid}` if unicorn_pid
|
|
44
|
+
`kill -TERM #{@wrangler_pid}` if @wrangler_pid
|
|
45
|
+
sleep 1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def perform_request
|
|
49
|
+
Curl::Easy.perform('http://localhost:7516').body_str
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'in general' do
|
|
53
|
+
before :each do
|
|
54
|
+
start_wrangler
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'quits (but leaves unicorn running) on receiving QUIT signal' do
|
|
58
|
+
Process.kill 'QUIT', @wrangler_pid
|
|
59
|
+
sleep 1
|
|
60
|
+
wrangler_running?.should_not be_true
|
|
61
|
+
unicorn_running?.should be_true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'quits (but leaves unicorn running) on receiving TERM signal' do
|
|
65
|
+
Process.kill 'TERM', @wrangler_pid
|
|
66
|
+
sleep 1
|
|
67
|
+
wrangler_running?.should_not be_true
|
|
68
|
+
unicorn_running?.should be_true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'quits (but leaves unicorn running) on receiving INT signal' do
|
|
72
|
+
Process.kill 'INT', @wrangler_pid
|
|
73
|
+
sleep 1
|
|
74
|
+
wrangler_running?.should_not be_true
|
|
75
|
+
unicorn_running?.should be_true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'quits if monitored unicorn process quits' do
|
|
79
|
+
Process.kill 'TERM', unicorn_pid
|
|
80
|
+
sleep 3
|
|
81
|
+
wrangler_running?.should_not be_true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'continues running after launch (so that process monitoring tools do not restart it)' do
|
|
85
|
+
sleep 3
|
|
86
|
+
wrangler_running?.should be_true
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when unicorn is not running' do
|
|
91
|
+
it 'launches unicorn on startup' do
|
|
92
|
+
start_wrangler
|
|
93
|
+
unicorn_running?.should be_true
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'when unicorn is already running' do
|
|
98
|
+
before :each do
|
|
99
|
+
start_unicorn
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'restarts unicorn on startup' do
|
|
103
|
+
original_pid = unicorn_pid
|
|
104
|
+
start_wrangler
|
|
105
|
+
sleep 3
|
|
106
|
+
unicorn_pid.should_not eql(original_pid)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'continues serving requests from both unicorns startup period' do
|
|
110
|
+
start_wrangler
|
|
111
|
+
100.times.map { perform_request }.uniq.size.should eql(2)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'stops serving requests from original unicorn' do
|
|
115
|
+
original_response = perform_request
|
|
116
|
+
start_wrangler
|
|
117
|
+
sleep 3
|
|
118
|
+
perform_request.should_not eql(original_response)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
before :each do
|
|
123
|
+
cleanup_processes
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
after :each do
|
|
127
|
+
cleanup_processes
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pid File.expand_path("../unicorn.pid", __FILE__)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'unicorn/wrangler/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "unicorn-wrangler"
|
|
8
|
+
spec.version = Unicorn::Wrangler::VERSION
|
|
9
|
+
spec.authors = ["Tom Ward"]
|
|
10
|
+
spec.email = ["tom@popdog.net"]
|
|
11
|
+
spec.description = %q{Wrangles unicorns}
|
|
12
|
+
spec.summary = %q{Helps manage unicorn processes}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency "unicorn"
|
|
24
|
+
spec.add_development_dependency "rspec"
|
|
25
|
+
spec.add_development_dependency "curb"
|
|
26
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: unicorn-wrangler
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tom Ward
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2013-06-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.3'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: unicorn
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - '>='
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: curb
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - '>='
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - '>='
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
description: Wrangles unicorns
|
|
84
|
+
email:
|
|
85
|
+
- tom@popdog.net
|
|
86
|
+
executables:
|
|
87
|
+
- unicorn-wrangler
|
|
88
|
+
extensions: []
|
|
89
|
+
extra_rdoc_files: []
|
|
90
|
+
files:
|
|
91
|
+
- .gitignore
|
|
92
|
+
- Gemfile
|
|
93
|
+
- LICENSE.txt
|
|
94
|
+
- README.md
|
|
95
|
+
- Rakefile
|
|
96
|
+
- bin/unicorn-wrangler
|
|
97
|
+
- lib/unicorn/wrangler.rb
|
|
98
|
+
- lib/unicorn/wrangler/version.rb
|
|
99
|
+
- spec/lib/unicorn/wrangler_spec.rb
|
|
100
|
+
- spec/support/config.ru
|
|
101
|
+
- spec/support/unicorn.conf.rb
|
|
102
|
+
- unicorn-wrangler.gemspec
|
|
103
|
+
homepage: ''
|
|
104
|
+
licenses:
|
|
105
|
+
- MIT
|
|
106
|
+
metadata: {}
|
|
107
|
+
post_install_message:
|
|
108
|
+
rdoc_options: []
|
|
109
|
+
require_paths:
|
|
110
|
+
- lib
|
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - '>='
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - '>='
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '0'
|
|
121
|
+
requirements: []
|
|
122
|
+
rubyforge_project:
|
|
123
|
+
rubygems_version: 2.0.2
|
|
124
|
+
signing_key:
|
|
125
|
+
specification_version: 4
|
|
126
|
+
summary: Helps manage unicorn processes
|
|
127
|
+
test_files:
|
|
128
|
+
- spec/lib/unicorn/wrangler_spec.rb
|
|
129
|
+
- spec/support/config.ru
|
|
130
|
+
- spec/support/unicorn.conf.rb
|