unicorn_relay 0.0.0 → 0.1.0
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/.gitignore +2 -0
- data/.travis.yml +3 -0
- data/README.md +90 -0
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/lib/unicorn_relay.rb +1 -0
- data/lib/unicorn_relay/forker.rb +24 -2
- data/lib/unicorn_relay/teardown.rb +4 -0
- data/lib/unicorn_relay/version.rb +1 -1
- data/spec/forker_spec.rb +1 -1
- data/unicorn_relay.gemspec +10 -7
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3690f55d5c212275a23edceb5b2f7f03482ba557
|
4
|
+
data.tar.gz: 454d018ead2c5a6855847700ed48def6b51f16ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b54c0ba3380997c021aea076fd3d306ec077adc72252453513128143c6b48eec7aa2cb7b5003803568edad93ccd9bcb4301682943f68f09672e99e1955de048d
|
7
|
+
data.tar.gz: 6b0ff1f688f821778dfed34ac8ac63ffacc6862aa24cc134197a2756f41c86b5c13b8b1fd1f9e537b0d2873f9792cb5b0927de7eaa8638c4245d8b3ec73285f5
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -0,0 +1,90 @@
|
|
1
|
+
# unicorn\_relay
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
The executable `unicorn_relay` contained in this gem allows you to supervise
|
6
|
+
unicorn via runit by relaying signals to it while keep running under
|
7
|
+
supervision and also handles the necessary work for handling pids, pid files,
|
8
|
+
etc.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
You can start `unicorn_relay` in your runit run script like this:
|
13
|
+
|
14
|
+
```
|
15
|
+
#!/bin/sh
|
16
|
+
|
17
|
+
# your ruby GC configuration variables: export UNICORN_GC=…
|
18
|
+
export PID_FILE="/some/where/pids/unicorn.pid"
|
19
|
+
|
20
|
+
cd "/some/where"
|
21
|
+
exec 2>&1
|
22
|
+
exec chpst -u my_user bundle exec unicorn_relay unicorn -c config/unicorn_config.rb
|
23
|
+
```
|
24
|
+
|
25
|
+
In your `unicorn_config.rb` configuration file you have to handle tearing down
|
26
|
+
an eventual old unicorn master when a new worker starts by calling
|
27
|
+
`UnicornRelay::Teardown#perform` as shown here:
|
28
|
+
|
29
|
+
```
|
30
|
+
before_fork do |server, worker|
|
31
|
+
UnicornRelay::Teardown.new(
|
32
|
+
pid_file: '/some/where/pids/unicorn.pid.oldbin',
|
33
|
+
server: server
|
34
|
+
).perform
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
The following signals will just be relayed to the forked unicorn processes:
|
39
|
+
|
40
|
+
```
|
41
|
+
HUP
|
42
|
+
USR1
|
43
|
+
USR2
|
44
|
+
TTIN
|
45
|
+
TTOU
|
46
|
+
WINCH
|
47
|
+
```
|
48
|
+
|
49
|
+
These signals will shutdown the supervised unicorn process:
|
50
|
+
|
51
|
+
```
|
52
|
+
QUIT
|
53
|
+
TERM
|
54
|
+
INT
|
55
|
+
```
|
56
|
+
|
57
|
+
In order to shutdown unicorn `unicorn_relay` just relays the `INT` and `QUIT`
|
58
|
+
signals, but changes the `TERM` signal to `QUIT` and then waits for the forked
|
59
|
+
processes to finish.
|
60
|
+
|
61
|
+
Now you can stop unicorn gracefully with the command
|
62
|
+
|
63
|
+
```
|
64
|
+
sv stop SERVICE
|
65
|
+
```
|
66
|
+
|
67
|
+
or w/o grace by executing:
|
68
|
+
|
69
|
+
```
|
70
|
+
sv interrupt SERVICE
|
71
|
+
```
|
72
|
+
|
73
|
+
If you run
|
74
|
+
|
75
|
+
```
|
76
|
+
sv 2 SERVICE
|
77
|
+
```
|
78
|
+
|
79
|
+
a new unicorn master is forked that is still controlled by the currently
|
80
|
+
running and supervised `unicorn_relay` script. The latter enables you to load
|
81
|
+
new code into your running app with a rolling restart behaviour, that is
|
82
|
+
without interruptions of service.
|
83
|
+
|
84
|
+
## Author
|
85
|
+
|
86
|
+
[Florian Frank](mailto:flori@ping.de)
|
87
|
+
|
88
|
+
## License
|
89
|
+
|
90
|
+
This software is licensed under the Apache 2.0 license.
|
data/Rakefile
CHANGED
@@ -11,7 +11,8 @@ GemHadar do
|
|
11
11
|
description 'Allow controlling unicorn via supervise by relaying signals to it'
|
12
12
|
test_dir 'spec'
|
13
13
|
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '.rvmrc',
|
14
|
-
'.AppleDouble', 'tags', '.byebug_history', '.DS_Store', 'errors.lst'
|
14
|
+
'.AppleDouble', 'tags', '.byebug_history', '.DS_Store', 'errors.lst',
|
15
|
+
'.yardoc', 'yard'
|
15
16
|
readme 'README.md'
|
16
17
|
title "#{name.camelize} -- More Math in Ruby"
|
17
18
|
licenses << 'Apache-2.0'
|
@@ -22,6 +23,7 @@ GemHadar do
|
|
22
23
|
development_dependency 'rake'
|
23
24
|
development_dependency 'simplecov'
|
24
25
|
development_dependency 'rspec'
|
26
|
+
development_dependency 'yard'
|
25
27
|
end
|
26
28
|
|
27
29
|
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/lib/unicorn_relay.rb
CHANGED
data/lib/unicorn_relay/forker.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
|
+
# This class forks a child unicorn process and handles relaying of signals to
|
2
|
+
# it.
|
1
3
|
class UnicornRelay::Forker
|
4
|
+
|
5
|
+
# This exception is caught in the start_control_loop method and stops its
|
6
|
+
# execution.
|
2
7
|
class StopException < StandardError; end
|
3
8
|
|
4
|
-
|
5
|
-
|
9
|
+
# @param name [ String ] The process name used in output and error messages (default is the basename of $0)
|
10
|
+
# @param pid_file [ String ] The path to the pid file of the unicorn master process
|
11
|
+
# @param argv [ Array ] The arguments for the forked unicorn process including the command itself (defaults to ARGV)
|
12
|
+
# @param env [ Hash ] The environment variables as a Hash used to fork the unicorn process (defaults to ENV)
|
13
|
+
def initialize(name: nil, pid_file: nil, argv: ARGV, env: ENV)
|
14
|
+
@name = name ? name : File.basename($0)
|
6
15
|
@pid_file = pid_file
|
7
16
|
@argv = argv
|
8
17
|
@env = env
|
@@ -14,11 +23,17 @@ class UnicornRelay::Forker
|
|
14
23
|
}
|
15
24
|
end
|
16
25
|
|
26
|
+
# First attempts to handle unicorn process where the pid was given in
|
27
|
+
# pid_file, that is interrupts them. Then starts the control loop that reacts
|
28
|
+
# to signals and relays them to the newly forked processes.
|
17
29
|
def start
|
18
30
|
handle_old_pid_file
|
19
31
|
start_control_loop
|
20
32
|
end
|
21
33
|
|
34
|
+
# Stops the control loop if called in its context by raising a
|
35
|
+
# UnicornRelay::Forker::StopException. You usally never have to/should do
|
36
|
+
# this.
|
22
37
|
def stop
|
23
38
|
stop_control_loop
|
24
39
|
end
|
@@ -127,10 +142,15 @@ class UnicornRelay::Forker
|
|
127
142
|
pgid
|
128
143
|
end
|
129
144
|
|
145
|
+
# @param signal [ Integer | Symbol | String ] a UNIX signal specifier
|
146
|
+
#
|
147
|
+
# Sends +signal+ to the controller unicorn processes.
|
130
148
|
def signal_process_group(signal)
|
131
149
|
Process.kill signal, -@pgid
|
132
150
|
end
|
133
151
|
|
152
|
+
# Check if a shutdown signal is pending, that is still to be sent to the
|
153
|
+
# forked unicorn processes.
|
134
154
|
def shutdown_signal_pending?
|
135
155
|
@shutdown_signal && !@shutdown_signal_sent_at
|
136
156
|
end
|
@@ -142,6 +162,8 @@ class UnicornRelay::Forker
|
|
142
162
|
signal_process_group @shutdown_signal
|
143
163
|
end
|
144
164
|
|
165
|
+
# Check if a shutdown signal was already sent a sufficient time ago and it
|
166
|
+
# might be time to try again.
|
145
167
|
def shutdown_signal_sent_before?
|
146
168
|
@shutdown_signal_sent_at && @shutdown_signal_sent_at - Time.now > 60
|
147
169
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
# Before forking anew, kill the unicorn master process that belongs to the
|
2
2
|
# .oldbin PID. This enables 0 downtime deploys.
|
3
3
|
class UnicornRelay::Teardown
|
4
|
+
# @param server [ Unicorn::HttpServer ] an instance of a unicorn server
|
5
|
+
# @param pid_file [ String ] the path to the old unicorn master's pid file (usually ending in ".oldbin")
|
4
6
|
def initialize(server:, pid_file:)
|
5
7
|
@server = server
|
6
8
|
@pid_file = pid_file
|
7
9
|
end
|
8
10
|
|
11
|
+
# Peforms the teardown of the old unicorn master from one of the workers
|
12
|
+
# forked by the new master, if the new master has a different pid file.
|
9
13
|
def perform
|
10
14
|
server_has_new_pid_file? && pid and kill_pid
|
11
15
|
end
|
data/spec/forker_spec.rb
CHANGED
data/unicorn_relay.gemspec
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: unicorn_relay 0.
|
2
|
+
# stub: unicorn_relay 0.1.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "unicorn_relay".freeze
|
6
|
-
s.version = "0.
|
6
|
+
s.version = "0.1.0"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Florian Frank".freeze]
|
11
|
-
s.date = "2016-10-
|
11
|
+
s.date = "2016-10-13"
|
12
12
|
s.description = "Allow controlling unicorn via supervise by relaying signals to it".freeze
|
13
13
|
s.email = "flori@ping.de".freeze
|
14
14
|
s.executables = ["unicorn_relay".freeze]
|
15
15
|
s.extra_rdoc_files = ["README.md".freeze, "lib/unicorn_relay.rb".freeze, "lib/unicorn_relay/forker.rb".freeze, "lib/unicorn_relay/teardown.rb".freeze, "lib/unicorn_relay/version.rb".freeze]
|
16
|
-
s.files = [".gitignore".freeze, ".rspec".freeze, ".utilsrc".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/unicorn_relay".freeze, "bin/unocorn".freeze, "lib/unicorn_relay.rb".freeze, "lib/unicorn_relay/forker.rb".freeze, "lib/unicorn_relay/teardown.rb".freeze, "lib/unicorn_relay/version.rb".freeze, "spec/forker_spec.rb".freeze, "spec/spec_helper.rb".freeze, "spec/teardown_spec.rb".freeze, "unicorn_relay.gemspec".freeze]
|
16
|
+
s.files = [".gitignore".freeze, ".rspec".freeze, ".travis.yml".freeze, ".utilsrc".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/unicorn_relay".freeze, "bin/unocorn".freeze, "lib/unicorn_relay.rb".freeze, "lib/unicorn_relay/forker.rb".freeze, "lib/unicorn_relay/teardown.rb".freeze, "lib/unicorn_relay/version.rb".freeze, "spec/forker_spec.rb".freeze, "spec/spec_helper.rb".freeze, "spec/teardown_spec.rb".freeze, "unicorn_relay.gemspec".freeze]
|
17
17
|
s.homepage = "http://flori.github.com/unicorn_relay".freeze
|
18
18
|
s.licenses = ["Apache-2.0".freeze]
|
19
19
|
s.rdoc_options = ["--title".freeze, "UnicornRelay -- More Math in Ruby".freeze, "--main".freeze, "README.md".freeze]
|
@@ -25,25 +25,28 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.specification_version = 4
|
26
26
|
|
27
27
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
28
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.
|
28
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.9.1"])
|
29
29
|
s.add_development_dependency(%q<rake>.freeze, [">= 0"])
|
30
30
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
31
31
|
s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
|
32
|
+
s.add_development_dependency(%q<yard>.freeze, [">= 0"])
|
32
33
|
s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.0"])
|
33
34
|
s.add_runtime_dependency(%q<mize>.freeze, [">= 0"])
|
34
35
|
else
|
35
|
-
s.add_dependency(%q<gem_hadar>.freeze, ["~> 1.
|
36
|
+
s.add_dependency(%q<gem_hadar>.freeze, ["~> 1.9.1"])
|
36
37
|
s.add_dependency(%q<rake>.freeze, [">= 0"])
|
37
38
|
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
38
39
|
s.add_dependency(%q<rspec>.freeze, [">= 0"])
|
40
|
+
s.add_dependency(%q<yard>.freeze, [">= 0"])
|
39
41
|
s.add_dependency(%q<tins>.freeze, ["~> 1.0"])
|
40
42
|
s.add_dependency(%q<mize>.freeze, [">= 0"])
|
41
43
|
end
|
42
44
|
else
|
43
|
-
s.add_dependency(%q<gem_hadar>.freeze, ["~> 1.
|
45
|
+
s.add_dependency(%q<gem_hadar>.freeze, ["~> 1.9.1"])
|
44
46
|
s.add_dependency(%q<rake>.freeze, [">= 0"])
|
45
47
|
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
46
48
|
s.add_dependency(%q<rspec>.freeze, [">= 0"])
|
49
|
+
s.add_dependency(%q<yard>.freeze, [">= 0"])
|
47
50
|
s.add_dependency(%q<tins>.freeze, ["~> 1.0"])
|
48
51
|
s.add_dependency(%q<mize>.freeze, [">= 0"])
|
49
52
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn_relay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.9.1
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.9.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
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'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: tins
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,7 @@ extra_rdoc_files:
|
|
108
122
|
files:
|
109
123
|
- ".gitignore"
|
110
124
|
- ".rspec"
|
125
|
+
- ".travis.yml"
|
111
126
|
- ".utilsrc"
|
112
127
|
- Gemfile
|
113
128
|
- README.md
|