Skip to content

Commit

Permalink
Merge pull request #90 from schneems/julienemo-add_rubocop
Browse files Browse the repository at this point in the history
Julienemo add rubocop
  • Loading branch information
schneems authored Aug 18, 2020
2 parents b9eb824 + a5b49ab commit 45b55a1
Show file tree
Hide file tree
Showing 23 changed files with 179 additions and 92 deletions.
22 changes: 22 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ matrix:
allow_failures:
- rvm: ruby-head
- rvm: rbx

install:
- bundle install

script:
- bundle exec rubocop
- bundle exec rake test
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Master

- 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)

Expand Down Expand Up @@ -31,3 +32,4 @@
## 0.0.3

- Fix memory metrics in on linux

6 changes: 5 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
source "https://rubygems.org"
# frozen_string_literal: true

source 'https://rubygems.org'

gemspec

gem 'rubocop', require: false
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# encoding: UTF-8
# frozen_string_literal: true

require 'bundler/gem_tasks'

Expand All @@ -7,7 +7,7 @@ require 'rake/testtask'

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'
Expand Down
10 changes: 6 additions & 4 deletions lib/puma_worker_killer.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'get_process_mem'

module PumaWorkerKiller
Expand All @@ -19,7 +21,7 @@ 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

Expand All @@ -28,9 +30,9 @@ def start(frequency = self.frequency, reaper = self.reaper)
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(nil, self.rolling_pre_term)).start
def enable_rolling_restart(frequency = rolling_restart_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(nil, rolling_pre_term)).start
end
end

Expand Down
2 changes: 2 additions & 0 deletions lib/puma_worker_killer/auto_reap.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module PumaWorkerKiller
class AutoReap
def initialize(timeout, reaper = Reaper.new)
Expand Down
18 changes: 8 additions & 10 deletions lib/puma_worker_killer/puma_memory.rb
Original file line number Diff line number Diff line change
@@ -1,13 +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
Expand All @@ -19,8 +19,6 @@ def term_worker(worker)

def term_largest_worker
largest_worker.term
# Process.wait(largest_worker.pid)
# rescue Errno::ECHILD
end

def workers_stopped?
Expand All @@ -32,7 +30,7 @@ def running?
end

def smallest_worker
smallest, _ = workers.to_a.first
smallest, = workers.to_a.first
smallest
end

Expand All @@ -42,7 +40,7 @@ def smallest_worker_memory
end

def largest_worker
largest_worker, _ = workers.to_a.last
largest_worker, = workers.to_a.last
largest_worker
end

Expand All @@ -57,7 +55,7 @@ def get_total(workers = set_workers)
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
Expand All @@ -73,11 +71,11 @@ def get_master
# 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
Expand Down
7 changes: 5 additions & 2 deletions lib/puma_worker_killer/reaper.rb
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -15,8 +17,9 @@ def get_total_memory

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."
Expand All @@ -29,7 +32,7 @@ def reap
# 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
Expand Down
13 changes: 8 additions & 5 deletions lib/puma_worker_killer/rolling_restart.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module PumaWorkerKiller
class RollingRestart
def initialize(master = nil, rolling_pre_term = nil)
Expand All @@ -10,16 +12,17 @@ def get_total_memory
@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: #{ total_memory } mb. Sending TERM to pid #{worker.pid}."
@rolling_pre_term.call(worker) unless @rolling_pre_term.nil?
@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
Expand Down
4 changes: 3 additions & 1 deletion lib/puma_worker_killer/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module PumaWorkerKiller
VERSION = "0.1.1"
VERSION = '0.1.1'
end
38 changes: 19 additions & 19 deletions puma_worker_killer.gemspec
Original file line number Diff line number Diff line change
@@ -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 = ["richard.schneeman+rubygems@gmail.com"]
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 = ['richard.schneeman+rubygems@gmail.com']
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', '< 5'
gem.add_development_dependency 'rack', '~> 1.6'
gem.add_development_dependency 'rake', '~> 10.1'
gem.add_development_dependency 'test-unit', '>= 0'
gem.add_development_dependency 'wait_for_it', '~> 0.1'
end
4 changes: 3 additions & 1 deletion test/fixtures/big.ru
Original file line number Diff line number Diff line change
@@ -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

Expand Down
4 changes: 3 additions & 1 deletion test/fixtures/config/puma_worker_killer_start.rb
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
4 changes: 3 additions & 1 deletion test/fixtures/default.ru
Original file line number Diff line number Diff line change
@@ -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

Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/fixture_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'securerandom'

require 'rack'
Expand All @@ -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
Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/on_calculation.ru
Original file line number Diff line number Diff line change
@@ -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

Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/pre_term.ru
Original file line number Diff line number Diff line change
@@ -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

Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/rolling_pre_term.ru
Original file line number Diff line number Diff line change
@@ -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.rolling_pre_term = lambda { |worker| puts("About to terminate (rolling) worker: #{worker.pid}") }
config.rolling_pre_term = ->(worker) { puts("About to terminate (rolling) worker: #{worker.pid}") }
end
PumaWorkerKiller.enable_rolling_restart(1) # 1 second

Expand Down
4 changes: 3 additions & 1 deletion test/fixtures/rolling_restart.ru
Original file line number Diff line number Diff line change
@@ -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.enable_rolling_restart(1) # 1 second

Expand Down
Loading

0 comments on commit 45b55a1

Please sign in to comment.