Hello community,
here is the log from the commit of package rubygem-puma_worker_killer for
openSUSE:Factory checked in at 2020-10-05 19:32:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-puma_worker_killer (Old)
and /work/SRC/openSUSE:Factory/.rubygem-puma_worker_killer.new.4249 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-puma_worker_killer"
Mon Oct 5 19:32:46 2020 rev:5 rq:838067 version:0.3.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/rubygem-puma_worker_killer/rubygem-puma_worker_killer.changes
2019-08-06 15:10:29.903771197 +0200
+++
/work/SRC/openSUSE:Factory/.rubygem-puma_worker_killer.new.4249/rubygem-puma_worker_killer.changes
2020-10-05 19:32:55.509151026 +0200
@@ -1,0 +2,25 @@
+Fri Sep 25 14:41:04 UTC 2020 - Stephan Kulow <[email protected]>
+
+updated to version 0.3.1
+ see installed CHANGELOG.md
+
+ ## Main
+
+ ## 0.3.1
+
+ - Relax puma dependency (#94)
+
+ ## 0.3.0
+
+ - Test on recent ruby versions #84
+ - Add option to adjust restart randomizer (#78)
+
+ ## 0.2.0
+
+ - Simplify workers memory calculation in PumaMemory‘s `get_total` method #81
+ - Add rubocop in gemspec and CI, with offenses corrected and unnecessary
cops disabled.
+ - Add `pre_term`-like `rolling_pre_term` config for terminations caused by
rolling restart (#86)
+ - Fix compatibility with ruby version 2.3.X (#87)
+
+
+-------------------------------------------------------------------
Old:
----
puma_worker_killer-0.1.1.gem
New:
----
puma_worker_killer-0.3.1.gem
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rubygem-puma_worker_killer.spec ++++++
--- /var/tmp/diff_new_pack.5bDVg3/_old 2020-10-05 19:32:56.373154670 +0200
+++ /var/tmp/diff_new_pack.5bDVg3/_new 2020-10-05 19:32:56.373154670 +0200
@@ -1,7 +1,7 @@
#
# spec file for package rubygem-puma_worker_killer
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
#
Name: rubygem-puma_worker_killer
-Version: 0.1.1
+Version: 0.3.1
Release: 0
%define mod_name puma_worker_killer
%define mod_full_name %{mod_name}-%{version}
@@ -32,7 +32,7 @@
BuildRequires: %{rubygem gem2rpm}
BuildRequires: %{ruby}
BuildRequires: ruby-macros >= 5
-Url: https://github.com/schneems/puma_worker_killer
+URL: https://github.com/schneems/puma_worker_killer
Source: https://rubygems.org/gems/%{mod_full_name}.gem
Source1: gem2rpm.yml
Summary: If you have a memory leak in your web code puma_worker_killer
can
++++++ puma_worker_killer-0.1.1.gem -> puma_worker_killer-0.3.1.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.github/workflows/check_changelog.yml
new/.github/workflows/check_changelog.yml
--- old/.github/workflows/check_changelog.yml 1970-01-01 01:00:00.000000000
+0100
+++ new/.github/workflows/check_changelog.yml 2020-09-22 20:38:14.000000000
+0200
@@ -0,0 +1,12 @@
+name: Check Changelog
+
+on: [pull_request]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - name: Check that CHANGELOG is touched
+ run: |
+ cat $GITHUB_EVENT_PATH | jq .pull_request.title | grep -i
'\[\(\(changelog skip\)\|\(ci skip\)\)\]' || git diff remotes/origin/${{
github.base_ref }} --name-only | grep CHANGELOG.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.rubocop.yml new/.rubocop.yml
--- old/.rubocop.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/.rubocop.yml 2020-09-22 20:38:14.000000000 +0200
@@ -0,0 +1,22 @@
+inherit_from: .rubocop_todo.yml
+
+Naming/AccessorMethodName:
+ Enabled: false
+
+Style/Documentation:
+ Enabled: false
+
+Style/HashSyntax:
+ Enabled: false
+
+Style/ModuleFunction:
+ Enabled: false
+
+Style/StringLiterals:
+ EnforcedStyle: single_quotes
+
+Style/StringLiteralsInInterpolation:
+ EnforcedStyle: double_quotes
+
+Gemspec/RequiredRubyVersion:
+ Enabled: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.rubocop_todo.yml new/.rubocop_todo.yml
--- old/.rubocop_todo.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/.rubocop_todo.yml 2020-09-22 20:38:14.000000000 +0200
@@ -0,0 +1,24 @@
+# This configuration was generated by
+# `rubocop --auto-gen-config`
+# on 2020-04-03 13:12:53 +0200 using RuboCop version 0.81.0.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 1
+# Configuration parameters: IgnoredMethods.
+Metrics/AbcSize:
+ Max: 21
+
+# Offense count: 1
+# Configuration parameters: CountComments, ExcludedMethods.
+Metrics/MethodLength:
+ Max: 11
+
+# Offense count: 32
+# Cop supports --auto-correct.
+# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes,
IgnoreCopDirectives, IgnoredPatterns.
+# URISchemes: http, https
+Layout/LineLength:
+ Max: 252
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.travis.yml new/.travis.yml
--- old/.travis.yml 2019-06-26 21:06:55.000000000 +0200
+++ new/.travis.yml 2020-09-22 20:38:14.000000000 +0200
@@ -1,12 +1,10 @@
language: ruby
rvm:
- - 1.9.3
- - 2.0.0
- - 2.1.10
- - 2.2.9
- - 2.3.6
- - 2.4.3
- - 2.5.0
+ - 2.3.8
+ - 2.4.10
+ - 2.5.8
+ - 2.6.6
+ - 2.7.1
- ruby-head
- rbx
before_install:
@@ -16,3 +14,10 @@
allow_failures:
- rvm: ruby-head
- rvm: rbx
+
+install:
+ - bundle install
+
+script:
+ - bundle exec rubocop
+ - bundle exec rake test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md 2019-06-26 21:06:55.000000000 +0200
+++ new/CHANGELOG.md 2020-09-22 20:38:14.000000000 +0200
@@ -1,3 +1,21 @@
+## Main
+
+## 0.3.1
+
+- Relax puma dependency (#94)
+
+## 0.3.0
+
+- Test on recent ruby versions #84
+- Add option to adjust restart randomizer (#78)
+
+## 0.2.0
+
+- Simplify workers memory calculation in PumaMemory‘s `get_total` method #81
+- Add rubocop in gemspec and CI, with offenses corrected and unnecessary cops
disabled.
+- Add `pre_term`-like `rolling_pre_term` config for terminations caused by
rolling restart (#86)
+- Fix compatibility with ruby version 2.3.X (#87)
+
## 0.1.1
- Allow PWK to be used with Puma 4 (#72)
@@ -25,3 +43,4 @@
## 0.0.3
- Fix memory metrics in on linux
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Gemfile new/Gemfile
--- old/Gemfile 2019-06-26 21:06:55.000000000 +0200
+++ new/Gemfile 2020-09-22 20:38:14.000000000 +0200
@@ -1,3 +1,7 @@
-source "https://rubygems.org"
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
gemspec
+
+gem 'rubocop', require: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md 2019-06-26 21:06:55.000000000 +0200
+++ new/README.md 2020-09-22 20:38:14.000000000 +0200
@@ -3,6 +3,22 @@
[](https://travis-ci.org/schneems/puma_worker_killer)
[](https://www.codetriage.com/schneems/puma_worker_killer)
+## !!!!!!!!!!!!!!!! STOP !!!!!!!!!!!!!!!!
+
+Before you use this gem, know that it is dangerous. If you have a memory
issue, you need to fix the issue. The original idea behind this gem is that it
would act as a temporary band-aid to buy you time to allow you to fix your
issues. If you turn this on and don't fix the underlying memory problems, then
things will only get worse over time.
+
+This gem can also make your performance WORSE. When a worker is killed, and
comes back it takes CPU cycles and time. If you are frequently restarting your
workers then you're killing your performance.
+
+Here are some places to start improving your understanding of memory behvior
in Ruby:
+
+- [Complete Guide to Rails Performance (Book)](https://www.railsspeed.com)
+- [How Ruby uses Memory](https://www.sitepoint.com/ruby-uses-memory/)
+- [Ruby Memory Use (Heroku Devcenter article I
maintain)](https://devcenter.heroku.com/articles/ruby-memory-use)
+- [Jumping off the Ruby Memory
Cliff](https://www.schneems.com/2017/04/12/jumping-off-the-memory-cliff/)
+- [How Ruby uses memory
(Talk)](https://www.schneems.com/2015/05/11/how-ruby-uses-memory.html) (you can
skip the first story in the video, the rest are about memory)
+- [Debugging a memory leak on
Heroku](https://blog.codeship.com/debugging-a-memory-leak-on-heroku/)
+
+If you still need this gem, proceed with caution.
## What
@@ -23,14 +39,7 @@
Then run `$ bundle install`
-<!--
-## Use
-
-> If you like `puma_worker_killer` consider using [puma_auto_tune
instead](https://github.com/schneems/puma_auto_tune). It handles memory leaks
and tunes your workers too!
-
--->
-
-## Turn on Rolling Restarts
+## Turn on Rolling Restarts - Heroku Mode
A rolling restart will kill each of your workers on a rolling basis. You set
the frequency which it conducts the restart. This is a simple way to keep
memory down as Ruby web programs generally increase memory usage over time. If
you're using Heroku [it is difficult to measure RAM from inside of a container
accurately](https://github.com/schneems/get_process_mem/issues/7), so it is
recommended to use this feature or use a [log-drain-based worker
killer](https://github.com/arches/whacamole). You can enable roling restarts by
running:
@@ -55,7 +64,7 @@
## Enable Worker Killing
-If you're not running on a containerized platform you can try to detect the
amount of memory you're using and only kill Puma workers when you're over that
limit. It may allow you to go for longer periods of time without killing a
worker however it is more error prone than rolling restarts. To enable
measurement based worker killing put this in your `config/puma.rb`:
+If you're not running on a containerized platform (like Heroku or Docker) you
can try to detect the amount of memory you're using and only kill Puma workers
when you're over that limit. It may allow you to go for longer periods of time
without killing a worker however it is more error prone than rolling restarts.
To enable measurement based worker killing put this in your `config/puma.rb`:
```ruby
# config/puma.rb
@@ -108,6 +117,7 @@
# PumaWorkerKiller: Consuming 54.34765625 mb with master and 2 workers.
config.pre_term = -> (worker) { puts "Worker #{worker.inspect} being killed"
}
+ config.rolling_pre_term = -> (worker) { puts "Worker #{worker.inspect} being
killed by rolling restart" }
end
PumaWorkerKiller.start
```
@@ -130,6 +140,17 @@
However you may want to collect more data, such as sending an event to an
error collection service like rollbar or airbrake. The `pre_term` lambda gets
called before any worker is killed by PWK for any reason.
+### rolling_pre_term
+
+`config.rolling_pre_term` will be called just prior to worker termination by
rolling restart when rolling restart is enabled.
+
+It is similar to `config.pre_term`.
+
+Difference:
+
+- `config.pre_term` is triggered only by terminations related with exceeding
RAM
+- `config.rolling_pre_term` is triggered only by terminations caused by
enabled rolling restart
+
### on_calculation
`config.on_calculation` will be called every time Puma Worker Killer
calculates memory usage (`config.frequency`). This may be useful for monitoring
your total puma application memory usage, which can be contrasted with other
application monitoring solutions.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Rakefile new/Rakefile
--- old/Rakefile 2019-06-26 21:06:55.000000000 +0200
+++ new/Rakefile 2020-09-22 20:38:14.000000000 +0200
@@ -1,4 +1,4 @@
-# encoding: UTF-8
+# frozen_string_literal: true
require 'bundler/gem_tasks'
@@ -7,7 +7,7 @@
task :default => [:test]
-test_task = Rake::TestTask.new(:test) do |t|
+Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer/auto_reap.rb
new/lib/puma_worker_killer/auto_reap.rb
--- old/lib/puma_worker_killer/auto_reap.rb 2019-06-26 21:06:55.000000000
+0200
+++ new/lib/puma_worker_killer/auto_reap.rb 2020-09-22 20:38:14.000000000
+0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module PumaWorkerKiller
class AutoReap
def initialize(timeout, reaper = Reaper.new)
@@ -16,6 +18,5 @@
end
end
end
-
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer/puma_memory.rb
new/lib/puma_worker_killer/puma_memory.rb
--- old/lib/puma_worker_killer/puma_memory.rb 2019-06-26 21:06:55.000000000
+0200
+++ new/lib/puma_worker_killer/puma_memory.rb 2020-09-22 20:38:14.000000000
+0200
@@ -1,12 +1,13 @@
+# frozen_string_literal: true
+
module PumaWorkerKiller
class PumaMemory
def initialize(master = nil)
@master = master || get_master
+ @workers = nil
end
- def master
- @master
- end
+ attr_reader :master
def size
workers.size
@@ -18,8 +19,6 @@
def term_largest_worker
largest_worker.term
- # Process.wait(largest_worker.pid)
- # rescue Errno::ECHILD
end
def workers_stopped?
@@ -31,7 +30,7 @@
end
def smallest_worker
- smallest, _ = workers.to_a.first
+ smallest, = workers.to_a.first
smallest
end
@@ -41,7 +40,7 @@
end
def largest_worker
- largest_worker, _ = workers.to_a.last
+ largest_worker, = workers.to_a.last
largest_worker
end
@@ -53,10 +52,10 @@
# Will refresh @workers
def get_total(workers = set_workers)
master_memory = GetProcessMem.new(Process.pid).mb
- worker_memory = workers.map {|_, mem| mem }.inject(&:+) || 0
+ worker_memory = workers.values.inject(:+) || 0
worker_memory + master_memory
end
- alias :get_total_memory :get_total
+ alias get_total_memory get_total
def workers
@workers || set_workers
@@ -72,11 +71,11 @@
# sorted by memory ascending (smallest first, largest last)
def set_workers
workers = {}
- @master.instance_variable_get("@workers").each do |worker|
+ @master.instance_variable_get('@workers').each do |worker|
workers[worker] = GetProcessMem.new(worker.pid).mb
end
if workers.any?
- @workers = Hash[ workers.sort_by {|_, mem| mem } ]
+ @workers = Hash[workers.sort_by { |_, mem| mem }]
else
{}
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer/reaper.rb
new/lib/puma_worker_killer/reaper.rb
--- old/lib/puma_worker_killer/reaper.rb 2019-06-26 21:06:55.000000000
+0200
+++ new/lib/puma_worker_killer/reaper.rb 2020-09-22 20:38:14.000000000
+0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module PumaWorkerKiller
class Reaper
def initialize(max_ram, master = nil, reaper_status_logs = true, pre_term
= nil, on_calculation = nil)
@@ -15,8 +17,9 @@
def reap
return false if @cluster.workers_stopped?
+
total = get_total_memory
- @on_calculation.call(total) unless @on_calculation.nil?
+ @on_calculation&.call(total)
if total > @max_ram
@cluster.master.log "PumaWorkerKiller: Out of memory.
#{@cluster.workers.count} workers consuming total: #{total} mb out of max:
#{@max_ram} mb. Sending TERM to pid #{@cluster.largest_worker.pid} consuming
#{@cluster.largest_worker_memory} mb."
@@ -29,7 +32,7 @@
# A new request comes in, Worker B takes it, and consumes 101 mb
memory
# term_largest_worker (previously here) gets called and terms Worker
B (thus not passing the about-to-be-terminated worker to `@pre_term`)
largest_worker = @cluster.largest_worker
- @pre_term.call(largest_worker) unless @pre_term.nil?
+ @pre_term&.call(largest_worker)
@cluster.term_worker(largest_worker)
elsif @reaper_status_logs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer/rolling_restart.rb
new/lib/puma_worker_killer/rolling_restart.rb
--- old/lib/puma_worker_killer/rolling_restart.rb 2019-06-26
21:06:55.000000000 +0200
+++ new/lib/puma_worker_killer/rolling_restart.rb 2020-09-22
20:38:14.000000000 +0200
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
module PumaWorkerKiller
class RollingRestart
- def initialize(master = nil)
+ def initialize(master = nil, rolling_pre_term = nil)
@cluster = PumaWorkerKiller::PumaMemory.new(master)
+ @rolling_pre_term = rolling_pre_term
end
# used for tes
@@ -9,12 +12,17 @@
@cluster.get_total_memory
end
- def reap(wait_between_worker_kill = 60) # seconds
+ def reap(seconds_between_worker_kill = 60)
+ # this will implicitly call set_workers
+ total_memory = get_total_memory
return false unless @cluster.running?
- @cluster.workers.each do |worker, ram|
- @cluster.master.log "PumaWorkerKiller: Rolling Restart.
#{@cluster.workers.count} workers consuming total: #{ get_total_memory } mb.
Sending TERM to pid #{worker.pid}."
+
+ @cluster.workers.each do |worker, _ram|
+ @cluster.master.log "PumaWorkerKiller: Rolling Restart.
#{@cluster.workers.count} workers consuming total: #{total_memory} mb. Sending
TERM to pid #{worker.pid}."
+ @rolling_pre_term&.call(worker)
+
worker.term
- sleep wait_between_worker_kill
+ sleep seconds_between_worker_kill
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer/version.rb
new/lib/puma_worker_killer/version.rb
--- old/lib/puma_worker_killer/version.rb 2019-06-26 21:06:55.000000000
+0200
+++ new/lib/puma_worker_killer/version.rb 2020-09-22 20:38:14.000000000
+0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module PumaWorkerKiller
- VERSION = "0.1.1"
+ VERSION = '0.3.1'
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/puma_worker_killer.rb
new/lib/puma_worker_killer.rb
--- old/lib/puma_worker_killer.rb 2019-06-26 21:06:55.000000000 +0200
+++ new/lib/puma_worker_killer.rb 2020-09-22 20:38:14.000000000 +0200
@@ -1,22 +1,29 @@
+# frozen_string_literal: true
+
require 'get_process_mem'
module PumaWorkerKiller
extend self
- attr_accessor :ram, :frequency, :percent_usage, :rolling_restart_frequency,
:reaper_status_logs, :pre_term, :on_calculation
+ attr_accessor :ram, :frequency, :percent_usage, :rolling_restart_frequency,
+ :rolling_restart_splay_seconds,
+ :reaper_status_logs, :pre_term, :rolling_pre_term,
:on_calculation
+
self.ram = 512 # mb
self.frequency = 10 # seconds
self.percent_usage = 0.99 # percent of RAM to use
self.rolling_restart_frequency = 6 * 3600 # 6 hours in seconds
+ self.rolling_restart_splay_seconds = 0.0..300.0 # 0 to 5 minutes in seconds
self.reaper_status_logs = true
self.pre_term = nil
+ self.rolling_pre_term = nil
self.on_calculation = nil
def config
yield self
end
- def reaper(ram = self.ram, percent = self.percent_usage, reaper_status_logs
= self.reaper_status_logs, pre_term = self.pre_term, on_calculation =
self.on_calculation)
+ def reaper(ram = self.ram, percent_usage = self.percent_usage,
reaper_status_logs = self.reaper_status_logs, pre_term = self.pre_term,
on_calculation = self.on_calculation)
Reaper.new(ram * percent_usage, nil, reaper_status_logs, pre_term,
on_calculation)
end
@@ -25,9 +32,11 @@
enable_rolling_restart(rolling_restart_frequency) if
rolling_restart_frequency
end
- def enable_rolling_restart(frequency = self.rolling_restart_frequency)
- frequency = frequency + rand(0..10.0) # so all workers don't restart at
the exact same time across multiple machines
- AutoReap.new(frequency, RollingRestart.new).start
+ def enable_rolling_restart(frequency = rolling_restart_frequency,
+ splay_seconds = rolling_restart_splay_seconds)
+ # Randomize so all workers don't restart at the exact same time across
multiple machines.
+ frequency += rand(splay_seconds)
+ AutoReap.new(frequency, RollingRestart.new(nil, rolling_pre_term)).start
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata 2019-06-26 21:06:55.000000000 +0200
+++ new/metadata 2020-09-22 20:38:14.000000000 +0200
@@ -1,36 +1,16 @@
--- !ruby/object:Gem::Specification
name: puma_worker_killer
version: !ruby/object:Gem::Version
- version: 0.1.1
+ version: 0.3.1
platform: ruby
authors:
- Richard Schneeman
-autorequire:
+autorequire:
bindir: bin
cert_chain: []
-date: 2019-06-26 00:00:00.000000000 Z
+date: 2020-09-22 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
- name: puma
- requirement: !ruby/object:Gem::Requirement
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- version: '2.7'
- - - "<"
- - !ruby/object:Gem::Version
- version: '5'
- type: :runtime
- prerelease: false
- version_requirements: !ruby/object:Gem::Requirement
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- version: '2.7'
- - - "<"
- - !ruby/object:Gem::Version
- version: '5'
-- !ruby/object:Gem::Dependency
name: get_process_mem
requirement: !ruby/object:Gem::Requirement
requirements:
@@ -45,47 +25,47 @@
- !ruby/object:Gem::Version
version: '0.2'
- !ruby/object:Gem::Dependency
- name: rack
+ name: puma
requirement: !ruby/object:Gem::Requirement
requirements:
- - - "~>"
+ - - ">="
- !ruby/object:Gem::Version
- version: '1.6'
- type: :development
+ version: '2.7'
+ type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - - "~>"
+ - - ">="
- !ruby/object:Gem::Version
- version: '1.6'
+ version: '2.7'
- !ruby/object:Gem::Dependency
- name: wait_for_it
+ name: rack
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '0.1'
+ version: '2.0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '0.1'
+ version: '2.0'
- !ruby/object:Gem::Dependency
name: rake
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '10.1'
+ version: '13.0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '10.1'
+ version: '13.0'
- !ruby/object:Gem::Dependency
name: test-unit
requirement: !ruby/object:Gem::Requirement
@@ -100,6 +80,20 @@
- - ">="
- !ruby/object:Gem::Version
version: '0'
+- !ruby/object:Gem::Dependency
+ name: wait_for_it
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - "~>"
+ - !ruby/object:Gem::Version
+ version: '0.1'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - "~>"
+ - !ruby/object:Gem::Version
+ version: '0.1'
description: " Kills pumas, the code kind "
email:
- [email protected]
@@ -107,7 +101,10 @@
extensions: []
extra_rdoc_files: []
files:
+- ".github/workflows/check_changelog.yml"
- ".gitignore"
+- ".rubocop.yml"
+- ".rubocop_todo.yml"
- ".travis.yml"
- CHANGELOG.md
- Gemfile
@@ -126,6 +123,7 @@
- test/fixtures/fixture_helper.rb
- test/fixtures/on_calculation.ru
- test/fixtures/pre_term.ru
+- test/fixtures/rolling_pre_term.ru
- test/fixtures/rolling_restart.ru
- test/puma_worker_killer_test.rb
- test/test_helper.rb
@@ -133,7 +131,7 @@
licenses:
- MIT
metadata: {}
-post_install_message:
+post_install_message:
rdoc_options: []
require_paths:
- lib
@@ -148,8 +146,8 @@
- !ruby/object:Gem::Version
version: '0'
requirements: []
-rubygems_version: 3.0.3
-signing_key:
+rubygems_version: 3.1.2
+signing_key:
specification_version: 4
summary: If you have a memory leak in your web code puma_worker_killer can
keep it
in check.
@@ -160,6 +158,7 @@
- test/fixtures/fixture_helper.rb
- test/fixtures/on_calculation.ru
- test/fixtures/pre_term.ru
+- test/fixtures/rolling_pre_term.ru
- test/fixtures/rolling_restart.ru
- test/puma_worker_killer_test.rb
- test/test_helper.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/puma_worker_killer.gemspec
new/puma_worker_killer.gemspec
--- old/puma_worker_killer.gemspec 2019-06-26 21:06:55.000000000 +0200
+++ new/puma_worker_killer.gemspec 2020-09-22 20:38:14.000000000 +0200
@@ -1,28 +1,28 @@
-# -*- encoding: utf-8 -*-
-lib = File.expand_path('../lib', __FILE__)
+# frozen_string_literal: true
+
+lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'puma_worker_killer/version'
Gem::Specification.new do |gem|
- gem.name = "puma_worker_killer"
+ gem.name = 'puma_worker_killer'
gem.version = PumaWorkerKiller::VERSION
- gem.authors = ["Richard Schneeman"]
- gem.email = ["[email protected]"]
- gem.description = %q{ Kills pumas, the code kind }
- gem.summary = %q{ If you have a memory leak in your web code
puma_worker_killer can keep it in check. }
- gem.homepage = "https://github.com/schneems/puma_worker_killer"
- gem.license = "MIT"
+ gem.authors = ['Richard Schneeman']
+ gem.email = ['[email protected]']
+ gem.description = ' Kills pumas, the code kind '
+ gem.summary = ' If you have a memory leak in your web code
puma_worker_killer can keep it in check. '
+ gem.homepage = 'https://github.com/schneems/puma_worker_killer'
+ gem.license = 'MIT'
- gem.files = `git ls-files`.split($/)
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
- gem.require_paths = ["lib"]
-
- gem.add_dependency "puma", ">= 2.7", "< 5"
- gem.add_dependency "get_process_mem", "~> 0.2"
- gem.add_development_dependency "rack", "~> 1.6"
- gem.add_development_dependency "wait_for_it", "~> 0.1"
- gem.add_development_dependency "rake", "~> 10.1"
- gem.add_development_dependency "test-unit", ">= 0"
+ gem.require_paths = ['lib']
+ gem.add_dependency 'get_process_mem', '~> 0.2'
+ gem.add_dependency 'puma', '>= 2.7'
+ gem.add_development_dependency 'rack', '~> 2.0'
+ gem.add_development_dependency 'rake', '~> 13.0'
+ gem.add_development_dependency 'test-unit', '>= 0'
+ gem.add_development_dependency 'wait_for_it', '~> 0.1'
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/big.ru new/test/fixtures/big.ru
--- old/test/fixtures/big.ru 2019-06-26 21:06:55.000000000 +0200
+++ new/test/fixtures/big.ru 2020-09-22 20:38:14.000000000 +0200
@@ -1,4 +1,6 @@
-load File.expand_path("../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
+
+load File.expand_path('fixture_helper.rb', __dir__)
PumaWorkerKiller.start
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/config/puma_worker_killer_start.rb
new/test/fixtures/config/puma_worker_killer_start.rb
--- old/test/fixtures/config/puma_worker_killer_start.rb 2019-06-26
21:06:55.000000000 +0200
+++ new/test/fixtures/config/puma_worker_killer_start.rb 2020-09-22
20:38:14.000000000 +0200
@@ -1,4 +1,6 @@
-load File.expand_path("../../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
+
+load File.expand_path('../fixture_helper.rb', __dir__)
before_fork do
require 'puma_worker_killer'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/default.ru new/test/fixtures/default.ru
--- old/test/fixtures/default.ru 2019-06-26 21:06:55.000000000 +0200
+++ new/test/fixtures/default.ru 2020-09-22 20:38:14.000000000 +0200
@@ -1,4 +1,6 @@
-load File.expand_path("../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
+
+load File.expand_path('fixture_helper.rb', __dir__)
PumaWorkerKiller.start
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/fixture_helper.rb
new/test/fixtures/fixture_helper.rb
--- old/test/fixtures/fixture_helper.rb 2019-06-26 21:06:55.000000000 +0200
+++ new/test/fixtures/fixture_helper.rb 2020-09-22 20:38:14.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'securerandom'
require 'rack'
@@ -10,10 +12,10 @@
config.frequency = Integer(ENV['PUMA_FREQUENCY']) if ENV['PUMA_FREQUENCY']
end
-puts "Frequency: #{ PumaWorkerKiller.frequency }" if ENV['PUMA_FREQUENCY']
+puts "Frequency: #{PumaWorkerKiller.frequency}" if ENV['PUMA_FREQUENCY']
class HelloWorld
- def response(env)
+ def response(_env)
[200, {}, ['Hello World']]
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/on_calculation.ru
new/test/fixtures/on_calculation.ru
--- old/test/fixtures/on_calculation.ru 2019-06-26 21:06:55.000000000 +0200
+++ new/test/fixtures/on_calculation.ru 2020-09-22 20:38:14.000000000 +0200
@@ -1,7 +1,9 @@
-load File.expand_path("../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
+
+load File.expand_path('fixture_helper.rb', __dir__)
PumaWorkerKiller.config do |config|
- config.on_calculation = lambda { |usage| puts("Current memory footprint:
#{usage} mb") }
+ config.on_calculation = ->(usage) { puts("Current memory footprint: #{usage}
mb") }
end
PumaWorkerKiller.start
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/pre_term.ru
new/test/fixtures/pre_term.ru
--- old/test/fixtures/pre_term.ru 2019-06-26 21:06:55.000000000 +0200
+++ new/test/fixtures/pre_term.ru 2020-09-22 20:38:14.000000000 +0200
@@ -1,7 +1,9 @@
-load File.expand_path("../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
+
+load File.expand_path('fixture_helper.rb', __dir__)
PumaWorkerKiller.config do |config|
- config.pre_term = lambda { |worker| puts("About to terminate worker:
#{worker.inspect}") }
+ config.pre_term = ->(worker) { puts("About to terminate worker:
#{worker.inspect}") }
end
PumaWorkerKiller.start
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/rolling_pre_term.ru
new/test/fixtures/rolling_pre_term.ru
--- old/test/fixtures/rolling_pre_term.ru 1970-01-01 01:00:00.000000000
+0100
+++ new/test/fixtures/rolling_pre_term.ru 2020-09-22 20:38:14.000000000
+0200
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+load File.expand_path('fixture_helper.rb', __dir__)
+
+PumaWorkerKiller.config do |config|
+ config.rolling_pre_term = ->(worker) { puts("About to terminate (rolling)
worker: #{worker.pid}") }
+end
+PumaWorkerKiller.enable_rolling_restart(1, 0..5.0) # 1 second, short 1-5s
splay.
+
+run HelloWorldApp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/fixtures/rolling_restart.ru
new/test/fixtures/rolling_restart.ru
--- old/test/fixtures/rolling_restart.ru 2019-06-26 21:06:55.000000000
+0200
+++ new/test/fixtures/rolling_restart.ru 2020-09-22 20:38:14.000000000
+0200
@@ -1,5 +1,7 @@
-load File.expand_path("../fixture_helper.rb", __FILE__)
+# frozen_string_literal: true
-PumaWorkerKiller.enable_rolling_restart(1) # 1 second
+load File.expand_path('fixture_helper.rb', __dir__)
+
+PumaWorkerKiller.enable_rolling_restart(1, 0..5.0) # 1 second, short 1-5s
splay.
run HelloWorldApp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/puma_worker_killer_test.rb
new/test/puma_worker_killer_test.rb
--- old/test/puma_worker_killer_test.rb 2019-06-26 21:06:55.000000000 +0200
+++ new/test/puma_worker_killer_test.rb 2020-09-22 20:38:14.000000000 +0200
@@ -1,76 +1,104 @@
+# frozen_string_literal: true
+
require 'test_helper'
class PumaWorkerKillerTest < Test::Unit::TestCase
-
def test_starts
port = 0 #
http://stackoverflow.com/questions/200484/how-do-you-find-a-free-tcp-server-port-using-ruby
- command = "bundle exec puma #{ fixture_path.join("default.ru") } -t 1:1
-w 2 --preload --debug -p #{ port }"
- options = { wait_for: "booted", timeout: 5, env: { "PUMA_FREQUENCY" => 1
} }
+ command = "bundle exec puma #{fixture_path.join("default.ru")} -t 1:1 -w
2 --preload --debug -p #{port}"
+ options = { wait_for: 'booted', timeout: 5, env: { 'PUMA_FREQUENCY' => 1
} }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "PumaWorkerKiller")
+ assert_contains(spawn, 'PumaWorkerKiller')
end
end
def test_without_preload
port = 0 #
http://stackoverflow.com/questions/200484/how-do-you-find-a-free-tcp-server-port-using-ruby
- command = "bundle exec puma #{ fixture_path.join("default.ru") } -t 1:1
-w 2 --debug -p #{ port } -C #{
fixture_path.join("config/puma_worker_killer_start.rb") }"
- options = { wait_for: "booted", timeout: 10, env: { "PUMA_FREQUENCY" => 1
} }
+ command = "bundle exec puma #{fixture_path.join("default.ru")} -t 1:1 -w
2 --debug -p #{port} -C
#{fixture_path.join("config/puma_worker_killer_start.rb")}"
+ options = { wait_for: 'booted', timeout: 10, env: { 'PUMA_FREQUENCY' => 1
} }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "PumaWorkerKiller")
+ assert_contains(spawn, 'PumaWorkerKiller')
end
end
def test_kills_large_app
- file = fixture_path.join("big.ru")
+ file = fixture_path.join('big.ru')
port = 0
- command = "bundle exec puma #{ file } -t 1:1 -w 2 --preload --debug -p #{
port }"
- options = { wait_for: "booted", timeout: 5, env: { "PUMA_FREQUENCY" => 1,
'PUMA_RAM' => 1} }
+ command = "bundle exec puma #{file} -t 1:1 -w 2 --preload --debug -p
#{port}"
+ options = { wait_for: 'booted', timeout: 5, env: { 'PUMA_FREQUENCY' => 1,
'PUMA_RAM' => 1 } }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "Out of memory")
+ assert_contains(spawn, 'Out of memory')
end
end
def test_pre_term
- file = fixture_path.join("pre_term.ru")
+ file = fixture_path.join('pre_term.ru')
port = 0
- command = "bundle exec puma #{ file } -t 1:1 -w 2 --preload --debug -p #{
port }"
- options = { wait_for: "booted", timeout: 5, env: { "PUMA_FREQUENCY" => 1,
'PUMA_RAM' => 1} }
+ command = "bundle exec puma #{file} -t 1:1 -w 2 --preload --debug -p
#{port}"
+ options = { wait_for: 'booted', timeout: 5, env: { 'PUMA_FREQUENCY' => 1,
'PUMA_RAM' => 1 } }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "Out of memory")
- assert_contains(spawn, "About to terminate worker:") # defined in
pre_term.ru
+ assert_contains(spawn, 'Out of memory')
+ assert_contains(spawn, 'About to terminate worker:') # defined in
pre_term.ru
end
end
def test_on_calculation
- file = fixture_path.join("on_calculation.ru")
+ file = fixture_path.join('on_calculation.ru')
port = 0
- command = "bundle exec puma #{ file } -t 1:1 -w 2 --preload --debug -p #{
port }"
- options = { wait_for: "booted", timeout: 5, env: { "PUMA_FREQUENCY" => 1,
'PUMA_RAM' => 1} }
+ command = "bundle exec puma #{file} -t 1:1 -w 2 --preload --debug -p
#{port}"
+ options = { wait_for: 'booted', timeout: 5, env: { 'PUMA_FREQUENCY' => 1,
'PUMA_RAM' => 1 } }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "Out of memory")
- assert_contains(spawn, "Current memory footprint:") # defined in
on_calculate.ru
+ assert_contains(spawn, 'Out of memory')
+ assert_contains(spawn, 'Current memory footprint:') # defined in
on_calculate.ru
end
end
def assert_contains(spawn, string)
- assert spawn.wait(string), "Expected logs to contain '#{string}' but it
did not, contents: #{ spawn.log.read }"
+ assert spawn.wait(string), "Expected logs to contain '#{string}' but it
did not, contents: #{spawn.log.read}"
end
def test_rolling_restart
+ file = fixture_path.join('rolling_restart.ru')
+ port = 0
+ command = "bundle exec puma #{file} -t 1:1 -w 2 --preload --debug -p
#{port}"
+ puts command.inspect
+ options = { wait_for: 'booted', timeout: 15, env: {} }
+
+ WaitForIt.new(command, options) do |spawn|
+ assert_contains(spawn, 'Rolling Restart')
+ end
+ end
+
+ def test_rolling_restart_worker_kill_check
+ file = fixture_path.join('rolling_restart.ru')
+ port = 0
+ command = "bundle exec puma #{file} -t 1:1 -w 1 --preload --debug -p
#{port}"
+ puts command.inspect
+ options = { wait_for: 'booted', timeout: 120, env: {} }
+
+ WaitForIt.new(command, options) do |spawn|
+ # at least 2 matches for TERM (so we set a timeout value longer - 120sec)
+ spawn.wait!(/TERM.*TERM/m)
+ term_ids = spawn.log.read.scan(/TERM to pid (\d*)/)
+ assert term_ids.sort == term_ids.uniq.sort
+ end
+ end
- file = fixture_path.join("rolling_restart.ru")
+ def test_rolling_pre_term
+ file = fixture_path.join('rolling_pre_term.ru')
port = 0
- command = "bundle exec puma #{ file } -t 1:1 -w 2 --preload --debug -p #{
port }"
+ command = "bundle exec puma #{file} -t 1:1 -w 2 --preload --debug -p
#{port}"
puts command.inspect
- options = { wait_for: "booted", timeout: 15, env: { } }
+ options = { wait_for: 'booted', timeout: 15, env: {} }
WaitForIt.new(command, options) do |spawn|
- assert_contains(spawn, "Rolling Restart")
+ assert_contains(spawn, 'Rolling Restart')
+ assert_contains(spawn, 'About to terminate (rolling) worker:') # defined
in rolling_pre_term.ru
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/test/test_helper.rb new/test/test_helper.rb
--- old/test/test_helper.rb 2019-06-26 21:06:55.000000000 +0200
+++ new/test/test_helper.rb 2020-09-22 20:38:14.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Bundler.require
require 'puma_worker_killer'
@@ -5,5 +7,5 @@
require 'wait_for_it'
def fixture_path
- Pathname.new(File.expand_path("../fixtures", __FILE__))
+ Pathname.new(File.expand_path('fixtures', __dir__))
end