stalin 0.1.2 → 0.2.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: d3aba1948f1211ea981734cb7eb62d1326536b0b
4
- data.tar.gz: 694df9a4c8732561d328a26ce17f64fa12eec669
3
+ metadata.gz: 76e53770ae0769f7bd129d9e29d33b614dd01376
4
+ data.tar.gz: 963fad2ce29f887865a71872c9cd41e64e629fd7
5
5
  SHA512:
6
- metadata.gz: 6b922bd545a388a1457220caa2fe3d308d82401b59a25e01b667db3810263a8019fb304a80c3031cb66a298928e57b33aa07c2d147ce64cfc77d5cb668d9085b
7
- data.tar.gz: fc6067a0ada40c95060d978c6615b9d0054ea2abc37a0062a54b91be2367f3ac6bae06c073166b1c2715f59e8e0200ab23b03d30836bb35170b04e3461791b0a
6
+ metadata.gz: 816bfc278b02ecea85221413c145d35a9feaab69a2ab78739aba8d892119b7d5b81cd42a15d350f2860d72649509e2f36b520f2d69b1926c68d1e6fc34e78b7b
7
+ data.tar.gz: 8aca03b3fe8cda1dcf950314e6f28aa7fa76e928abff60ea0061e72fb628fc1136337a05eb050055c4ecfeb923b0b13d9b13e30e9b45982c08f045171c2baae5
data/README.md CHANGED
@@ -26,20 +26,22 @@ Servers known NOT to work:
26
26
  As you can see, we are far short of our _goal_ to support many servers! More to come as needed;
27
27
  let me know what you need!
28
28
 
29
- # Installation
29
+ # User's Guide
30
+
31
+ ## Installation
30
32
 
31
33
  Just include stalin in your Gemfile.
32
34
 
33
35
  gem 'stalin'
34
36
 
35
- # Usage
37
+ ## Usage
36
38
 
37
39
  Decide on which application server you will use. Add some lines to your `config.ru` to
38
40
  install a suitable Stalin middleware.
39
41
 
40
42
  Because different app servers have different signal-handling and restart semantics, we
41
- must specialize Stalin's behavior; this is done with a base class (Stalin::Adapter::Rack)
42
- plus one derived class per supported application server.
43
+ must specialize Stalin's behavior; this is done with an abstract base class
44
+ (Stalin::Adapter::Rack) plus one derived class per supported application server.
43
45
 
44
46
  # Gem that kills app processes when their heap becomes too fragmented.
45
47
  require 'stalin'
@@ -50,17 +52,40 @@ plus one derived class per supported application server.
50
52
  # Each worker will shutdown at some point between 192MB and 256MB of memory usage.
51
53
  use Stalin::Adapter::Unicorn, (192*mb), (256*mb)
52
54
 
53
- If you instantiate Stalin::Adapter::Rack directly, you have two choices:
54
- - Pass three parameters (app, graceful-shutdown signal and abrupt-shutdown signal) to decide on signalling behavior yourself
55
- - Pass one parameter (app) to let Stalin decide which adapter to use based on which server is resident in memory
56
-
57
- Instantiating the Rack middleware with one parameter is deprecated; we'd much rather you be
58
- explicit about your application server than rely on our heuristic!
59
-
60
- # Tuning
55
+ ## Tuning
61
56
 
62
57
  Consult the documentation for your adapter's `#initialize` to learn how to tune Stalin's behavior.
63
58
 
59
+ # Developer's Guide
60
+
61
+ This gem is a work in progress; the docs are okay, but test coverage is
62
+ nonexistent. Whenever you make changes, please do some smoke tests by yourself.
63
+
64
+ ## Smoke Tests
65
+
66
+ The `fixtures` subdirectory contains rackup files for both supported application
67
+ servers; you can use these to test the three supported permutations.
68
+
69
+ When you run puma or rainbows, it will begin listening on a port of its
70
+ choosing; use curl or similar to send it Web requests and cause a large
71
+ memory leak with every request. Each worker process should shutdown after the
72
+ first request, because the leak is large and the hardcoded limit for puma is
73
+ very small.
74
+
75
+ Verify that stalin is restarting the app servers and that your requests all
76
+ respond with 200 and not 502, 503 or other funny errors.
77
+
78
+ ### Unicorn
79
+
80
+ bundle exec unicorn fixtures/unicorn.ru
81
+ ### Single-Process Puma
82
+
83
+ bundle exec puma fixtures/puma.ru
84
+
85
+ ### Multi-Process Puma
86
+
87
+ bundle exec puma -w 1 fixtures/puma.ru
88
+
64
89
  # Special Thanks
65
90
 
66
91
  - [@kzk](http://github.com/kzk/) for the [unicorn-worker-killer] gem which this is derived from
data/Rakefile CHANGED
@@ -9,6 +9,7 @@ Jeweler::Tasks.new do |gem|
9
9
  gem.description = %Q{Kill Web application workers based on arbitrary conditions.}
10
10
  gem.email = "xeger@xeger.net"
11
11
  gem.authors = ["Tony Spataro"]
12
+ gem.required_ruby_version = '~> 2.0'
12
13
  gem.files.exclude ".rspec"
13
14
  gem.files.exclude "Gemfile*"
14
15
  gem.files.exclude "fixtures/**/*"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -1,43 +1,10 @@
1
1
  module Stalin::Adapter
2
- # A low-tech but reliable solution that invokes stalin using Rack middleware.
3
- # This is suitable for application srvers that use a master-and-workers
4
- # process architecture, wohse workers respond to a graceful shutdown signal,
5
- # and whose masters spawn new workers as needed.
6
- #
7
- # This functions as a base class for server-specific middlewares, and can be used if
2
+ # Abstract base class for server-specific Rack middlewares.
8
3
  # there is an app server that uses a signalling strategy not explicitly supported by Stalin.
9
4
  class Rack
10
5
  # Conversion constant for human-readable memory amounts in log messages.
11
6
  MB = Float(1024**2)
12
7
 
13
- # Construct a new middleware. If all six arguments are passed, construct an instance
14
- # of this class; otherwise, use a heuristic to construct an instance of a suitable
15
- # derived class.
16
- #
17
- # @raise [ArgumentError] if an incorrect number of arguments is passed
18
- # @raise [RuntimeError] if 0..5 arguments and the heuristic can't figure out which signals to use
19
- def self.new(*args)
20
- if self == Rack && args.length < 3
21
- # Warn that this shim will go away in v1
22
- warn "Stalin::Adapter::Rack.new with fewer than 3 arguments is deprecated; please instantiate a derived class e.g. Unicorn or Puma"
23
-
24
- # Use a heuristic to decide on the correct adapter and instantiate a derived class.
25
- if defined?(::Unicorn)
26
- middleware = Unicorn.allocate
27
- elsif defined?(::Puma)
28
- middleware = Puma.allocate
29
- else
30
- raise RuntimeError, "Cannot determine a suitable Stalin adapter; please instantiate this class with six arguments"
31
- end
32
-
33
- # Initialize our new object (ugh)
34
- middleware.instance_eval { initialize(*args) }
35
- middleware
36
- else
37
- super
38
- end
39
- end
40
-
41
8
  # Create a middleware instance.
42
9
  #
43
10
  # @param [#call] app inner Rack application
@@ -48,7 +15,7 @@ module Stalin::Adapter
48
15
  # @param [Integer] cycle how frequently to check memory consumption (# requests)
49
16
  # @param [Boolean] verbose log extra information
50
17
  # @param [Array] signals pair of two Symbol signal-names: one for "graceful shutdown please" and one for "terminate immediately"
51
- def initialize(app, graceful, abrupt, min=1024**3, max=2*1024**3, cycle=16, verbose=false)
18
+ def initialize(app, graceful, abrupt, min, max, cycle, verbose)
52
19
  @app = app
53
20
  @graceful = graceful
54
21
  @abrupt = abrupt
@@ -56,6 +23,7 @@ module Stalin::Adapter
56
23
  @max = max
57
24
  @cycle = cycle
58
25
  @verbose = verbose
26
+ @req = 0
59
27
  end
60
28
 
61
29
  def call(env)
@@ -64,22 +32,26 @@ module Stalin::Adapter
64
32
  logger = logger_for(env)
65
33
 
66
34
  begin
67
- @lim ||= @min + randomize(@max - @min + 1)
68
- @req ||= 0
69
- @req += 1
35
+ if @req == 0
36
+ # First-time initialization. Deferred until first request so we can
37
+ # ensure that init-time log output goes to the right place.
38
+ @lim = @min + randomize(@max - @min + 1)
39
+ @req = 0
40
+ @watcher = ::Stalin::Watcher.new(Process.pid)
41
+ @killer = ::Stalin::Killer.new(Process.pid, @graceful, @abrupt)
42
+ logger.info "stalin (pid: %d) startup; limit=%.1f MB, graceful=SIG%s (abrupt=SIG%s after %d tries)" %
43
+ [Process.pid, @lim / MB, @graceful, @abrupt, Stalin::Killer::MAX_GRACEFUL]
44
+ end
45
+
46
+ @req += 1
70
47
 
71
48
  if @req % @cycle == 0
72
- @req = 0
73
- @watcher ||= ::Stalin::Watcher.new(Process.pid)
74
- @killer ||= ::Stalin::Killer.new(Process.pid, @graceful, @abrupt)
75
49
  if (used = @watcher.watch) > @lim
76
50
  sig = @killer.kill
77
- @watcher.watch
78
- logger.info "stalin (pid: %d) send SIG%s; memory usage %.1f MB > %.1f MB" %
51
+ logger.info "stalin (pid: %d) send SIG%s; %.1f MB > %.1f MB" %
79
52
  [Process.pid, sig, used / MB, @lim / MB]
80
- @cycle = 2
81
53
  elsif @verbose
82
- logger.info "stalin (pid: %d) soldiers on; memory usage %.1f MB < %.1f MB" %
54
+ logger.info "stalin (pid: %d) soldiers on; %.1f MB < %.1f MB" %
83
55
  [Process.pid, used / MB, @lim / MB]
84
56
  end
85
57
  end
@@ -94,7 +66,7 @@ module Stalin::Adapter
94
66
  private
95
67
 
96
68
  def randomize(integer)
97
- RUBY_VERSION > "1.9" ? Random.rand(integer.abs) : rand(integer)
69
+ Random.rand(integer.abs)
98
70
  end
99
71
 
100
72
  def logger_for(env)
data/stalin.gemspec CHANGED
@@ -2,17 +2,20 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: stalin 0.2.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "stalin"
8
- s.version = "0.1.2"
9
+ s.version = "0.2.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Tony Spataro"]
12
- s.date = "2015-04-21"
14
+ s.date = "2015-08-17"
13
15
  s.description = "Kill Web application workers based on arbitrary conditions."
14
16
  s.email = "xeger@xeger.net"
15
17
  s.extra_rdoc_files = [
18
+ "CHANGELOG.md",
16
19
  "LICENSE",
17
20
  "README.md"
18
21
  ]
@@ -36,8 +39,8 @@ Gem::Specification.new do |s|
36
39
  ]
37
40
  s.homepage = "https://github.com/xeger/stalin"
38
41
  s.licenses = ["MIT"]
39
- s.require_paths = ["lib"]
40
- s.rubygems_version = "2.0.14"
42
+ s.required_ruby_version = Gem::Requirement.new("~> 2.0")
43
+ s.rubygems_version = "2.4.5"
41
44
  s.summary = "Kill rack"
42
45
 
43
46
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stalin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Spataro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-21 00:00:00.000000000 Z
11
+ date: 2015-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jeweler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '2.0'
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
26
  version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sinatra
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: unicorn
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '4.8'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4.8'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thin
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '1.6'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.6'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: puma
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '2.11'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '2.11'
97
97
  description: Kill Web application workers based on arbitrary conditions.
@@ -99,6 +99,7 @@ email: xeger@xeger.net
99
99
  executables: []
100
100
  extensions: []
101
101
  extra_rdoc_files:
102
+ - CHANGELOG.md
102
103
  - LICENSE
103
104
  - README.md
104
105
  files:
@@ -128,17 +129,17 @@ require_paths:
128
129
  - lib
129
130
  required_ruby_version: !ruby/object:Gem::Requirement
130
131
  requirements:
131
- - - '>='
132
+ - - "~>"
132
133
  - !ruby/object:Gem::Version
133
- version: '0'
134
+ version: '2.0'
134
135
  required_rubygems_version: !ruby/object:Gem::Requirement
135
136
  requirements:
136
- - - '>='
137
+ - - ">="
137
138
  - !ruby/object:Gem::Version
138
139
  version: '0'
139
140
  requirements: []
140
141
  rubyforge_project:
141
- rubygems_version: 2.0.14
142
+ rubygems_version: 2.4.5
142
143
  signing_key:
143
144
  specification_version: 4
144
145
  summary: Kill rack