unicorn_relay 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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