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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb391afaecdf7ee75869e6d86ef3bcf590e60471
4
- data.tar.gz: 76fe237036b5be4b6e2275217b59c8f415a3e270
3
+ metadata.gz: 3690f55d5c212275a23edceb5b2f7f03482ba557
4
+ data.tar.gz: 454d018ead2c5a6855847700ed48def6b51f16ca
5
5
  SHA512:
6
- metadata.gz: 283caa1b2bda67e62c2158f9dbdbfab85c4877c71a62648c444ae06b2605fcdd278eb4026fcd753b60ef758f0dc7cb5860ddde996a9b8a64f49e2209929da931
7
- data.tar.gz: 37dc59b4bd7be89f5f30b15b73e7cb7fdda487fab3b9299a4e1a5afd9b78e1443926ab652823f05d550da273cb07248b74b63c3872d4e5a9c9f0f626d9921aad
6
+ metadata.gz: b54c0ba3380997c021aea076fd3d306ec077adc72252453513128143c6b48eec7aa2cb7b5003803568edad93ccd9bcb4301682943f68f09672e99e1955de048d
7
+ data.tar.gz: 6b0ff1f688f821778dfed34ac8ac63ffacc6862aa24cc134197a2756f41c86b5c13b8b1fd1f9e537b0d2873f9792cb5b0927de7eaa8638c4245d8b3ec73285f5
data/.gitignore CHANGED
@@ -3,8 +3,10 @@
3
3
  .DS_Store
4
4
  .byebug_history
5
5
  .rvmrc
6
+ .yardoc
6
7
  Gemfile.lock
7
8
  coverage
8
9
  errors.lst
9
10
  pkg
10
11
  tags
12
+ yard
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 2.3.1
3
+ sudo: false
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.0.0
1
+ 0.1.0
@@ -1,6 +1,7 @@
1
1
  require 'tins/xt'
2
2
  require 'mize'
3
3
 
4
+ # All classes used by unicorn_relay are defined under this namespace.
4
5
  module UnicornRelay
5
6
  end
6
7
 
@@ -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
- def initialize(script_path: $0, pid_file: nil, argv: ARGV, env: ENV)
5
- @name = File.basename(script_path)
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
@@ -1,6 +1,6 @@
1
1
  module UnicornRelay
2
2
  # UnicornRelay version
3
- VERSION = '0.0.0'
3
+ VERSION = '0.1.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -11,7 +11,7 @@ describe UnicornRelay::Forker do
11
11
 
12
12
  let :forker do
13
13
  described_class.new(
14
- script_path: 'foo/bar/unicorn_relay',
14
+ name: 'unicorn_relay',
15
15
  pid_file: pid_file
16
16
  )
17
17
  end
@@ -1,19 +1,19 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: unicorn_relay 0.0.0 ruby lib
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.0.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"
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.8.0"])
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.8.0"])
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.8.0"])
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.0.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 00:00:00.000000000 Z
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.8.0
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.8.0
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