worker_killer 1.0.2.187852 → 1.0.3.189098

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
  SHA256:
3
- metadata.gz: 0cde26e5d9705270605884443084f3dada5182e12ce9cba38c91ef5206837ced
4
- data.tar.gz: 8ebe3a9edafa87bafb84edd1f52277bb62dc9db7484fa4f0515ec0acaaf5d9ac
3
+ metadata.gz: 833e8af55d32a033c006174376730eeb13939b9a71428bced0bd6fbbf31a3fbf
4
+ data.tar.gz: 8867071b25e0bcfaea641fdc5595794cfd4ad166da32f6aa55d600322e925bf0
5
5
  SHA512:
6
- metadata.gz: 8bb89c7851d4dd6a127fa33273ca6c64e899c1d03d7e44709435a940944e7dff074a2f56f794221790464836d174fbb2dfa02f1ee08cf333a4b05342c6b0e1d7
7
- data.tar.gz: ca33356f8884b182c7ad06883b337168b563f105829f5f587471b87972d76b3738e97f5bb7e6cbcfe335d630cf386cb2026d805eb1ff1a264d60961ae5d27735
6
+ metadata.gz: 7ceb0b3fdfb56a24480ff28a809dcb6bf96613d31fefa2c9fd2eca60e12205ef211c160683e6c9f42bb06928126476393430d3d6972da497872c886d2fcdd319
7
+ data.tar.gz: c74db721a9e0684598abc4f0d40f1aeb7b55be6d77e14a214b15431d0d1012272df43ff584d41673f8f5f28b5037ef441ae39938c093b1aba7a5d85d3fadd60f
@@ -5,36 +5,57 @@ module WorkerKiller
5
5
 
6
6
  attr_reader :min, :max, :limit, :started_at, :check_cycle
7
7
 
8
- def initialize(min: (1024**3), max: (2 * (1024**3)), check_cycle: 16, verbose: false)
9
- @min = min
10
- @max = max
11
- @limit = @min + WorkerKiller.randomize(@max - @min + 1)
8
+ def initialize(min:, max:, check_cycle: 16, verbose: false)
9
+ if min
10
+ # set static memory limits
11
+ @min = min
12
+ @max = max
13
+ @limit = @min + WorkerKiller.randomize(@max - @min + 1)
14
+ @limit_mb = (@limit / 1024 / 1024).round(1)
15
+ else
16
+ # prepare for relative memory limits
17
+ @max_percent = max
18
+ end
19
+
12
20
  @check_cycle = check_cycle
13
21
  @check_count = 0
14
22
  @verbose = verbose
15
23
  end
16
24
 
17
25
  def check
18
- return nil if @limit <= 1024**2
19
-
20
26
  @started_at ||= Time.now
21
27
  @check_count += 1
22
28
 
23
29
  return nil if (@check_count % @check_cycle) != 0
24
30
 
25
31
  rss = GetProcessMem.new.bytes
32
+ # initialize relative memory limits on first check
33
+ set_limits(rss, rss + rss * @max_percent) if min.nil?
34
+
35
+ do_check(rss)
36
+ end
37
+
38
+ def do_check(rss)
39
+ rss_mb = (rss / 1024 / 1024).round(1)
40
+
26
41
  if @verbose
27
- logger.info "#{self.class}: worker (pid: #{Process.pid}) using #{rss} bytes(#{rss / 1024 / 1024}mb)."
42
+ logger.info "#{self.class}: worker (pid: #{Process.pid}) using #{rss_mb} MB (of #{@limit_mb} MB)"
28
43
  end
29
44
  @check_count = 0
30
45
 
31
46
  return false if rss <= @limit
32
47
 
33
- logger.warn "#{self.class}: worker (pid: #{Process.pid}) exceeds memory limit (#{rss} bytes > #{@limit} bytes)"
48
+ logger.warn "#{self.class}: worker (pid: #{Process.pid}) exceeds memory limit (#{rss_mb} MB > #{@limit_mb} MB)"
34
49
 
35
50
  true
36
51
  end
37
52
 
53
+ def set_limits(min, max)
54
+ @min = min
55
+ @limit = @max = max
56
+ @limit_mb = (@limit / 1024 / 1024).round(1)
57
+ end
58
+
38
59
  def logger
39
60
  WorkerKiller.configuration.logger
40
61
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module WorkerKiller
4
4
 
5
- VERSION = '1.0.2'
5
+ VERSION = '1.0.3'
6
6
 
7
7
  end
8
8
 
@@ -1,13 +1,12 @@
1
1
  RSpec.describe WorkerKiller::DelayedJobPlugin::JobsLimiter do
2
-
3
- let(:killer) {double}
2
+ let(:killer) { double }
4
3
  subject(:plugin){ described_class.new(killer: killer) }
5
4
 
6
5
  context 'DelayedJob initialization' do
7
6
  let(:lifecycle) { double }
8
7
  subject(:instance) { plugin.new(lifecycle) }
9
-
10
- it do
8
+
9
+ it do
11
10
  expect(lifecycle).to receive(:after).with(:perform).and_yield
12
11
  expect(lifecycle).to receive(:after).with(:loop).and_yield
13
12
  instance
@@ -1,13 +1,12 @@
1
1
  RSpec.describe WorkerKiller::DelayedJobPlugin::OOMLimiter do
2
-
3
- let(:killer) {double}
4
- subject(:plugin){ described_class.new(killer: killer) }
2
+ let(:killer) { double }
3
+ subject(:plugin){ described_class.new(min: (1024**3), max: (2 * (1024**3)), killer: killer) }
5
4
 
6
5
  context 'DelayedJob initialization' do
7
6
  let(:lifecycle) { double }
8
7
  subject(:instance) { plugin.new(lifecycle) }
9
-
10
- it do
8
+
9
+ it do
11
10
  expect(lifecycle).to receive(:after).with(:perform).and_yield
12
11
  expect(lifecycle).to receive(:after).with(:loop).and_yield
13
12
  instance
@@ -2,13 +2,10 @@ RSpec.describe WorkerKiller::MemoryLimiter do
2
2
  let(:logger){ Logger.new(nil) }
3
3
 
4
4
  subject{ described_class.new(**options) }
5
- let(:mb){ 1024 * 1024 }
6
- let(:min){ rand(50..100) * mb }
7
- let(:max){ min + rand(100) * mb }
8
5
  let(:check_cycle){ 5 }
9
- let(:options){ { min: min, max: max, check_cycle: check_cycle, verbose: true} }
6
+ let(:options){ { min: min, max: max, check_cycle: check_cycle, verbose: true } }
7
+ let(:memory) { instance_double(GetProcessMem) }
10
8
 
11
- it { is_expected.to have_attributes(min: min, max: max, limit: a_value_between(min, max)) }
12
9
 
13
10
  def skip_cycles(object, cycles)
14
11
  (cycles - 1).times do
@@ -16,28 +13,68 @@ RSpec.describe WorkerKiller::MemoryLimiter do
16
13
  end
17
14
  end
18
15
 
19
- it 'expect to skip check while less than cycle count' do
20
- expect(GetProcessMem).not_to receive(:new)
21
-
22
- skip_cycles(subject, check_cycle)
16
+ before do
17
+ allow(GetProcessMem).to receive(:new).and_return(memory)
23
18
  end
24
19
 
25
- it 'expect to skip check after cycle count reached' do
26
- memory = instance_double(GetProcessMem)
27
- expect(memory).to receive(:bytes).and_return(min - 1)
28
- expect(GetProcessMem).to receive(:new).and_return(memory)
20
+ context 'fixed memory limit' do
21
+ let(:mb){ 1024 * 1024 }
22
+ let(:min){ rand(50..100) * mb }
23
+ let(:max){ min + rand(100) * mb }
24
+
25
+ it { is_expected.to have_attributes(min: min, max: max, limit: a_value_between(min, max)) }
26
+
27
+ it 'expect to skip check while less than cycle count' do
28
+ expect(GetProcessMem).not_to receive(:new)
29
+
30
+ skip_cycles(subject, check_cycle)
31
+ end
32
+
33
+ it 'expect to skip check after cycle count reached' do
34
+ expect(memory).to receive(:bytes).and_return(min - 1)
35
+
36
+ skip_cycles(subject, check_cycle)
37
+ expect(subject.check).to be_falsey
38
+ end
29
39
 
30
- skip_cycles(subject, check_cycle)
31
- expect(subject.check).to be_falsey
40
+ it 'expect call reaction when check succeded' do
41
+ expect(memory).to receive(:bytes).and_return(subject.limit + 1)
42
+
43
+ skip_cycles(subject, check_cycle)
44
+ expect(subject.check).to be_truthy
45
+ end
32
46
  end
33
47
 
34
- it 'expect call reaction when check succeded' do
35
- memory = instance_double(GetProcessMem)
36
- expect(memory).to receive(:bytes).and_return(subject.limit + 1)
37
- expect(GetProcessMem).to receive(:new).and_return(memory)
48
+ context 'relative memory limit' do
49
+ let(:min){ nil }
50
+ let(:max){ 0.5 }
51
+ let(:rss) { 100 * 1024 * 1024 }
52
+ let(:min_expected) { rss }
53
+ let(:max_expected) { min_expected + min_expected * max }
38
54
 
39
- skip_cycles(subject, check_cycle)
40
- expect(subject.check).to be_truthy
55
+ it { is_expected.to have_attributes(min: nil, max: nil, limit: nil) }
56
+
57
+ it 'expect to initialize limits on first check' do
58
+ expect(memory).to receive(:bytes).and_return(rss)
59
+
60
+ skip_cycles(subject, check_cycle)
61
+ is_expected.to have_attributes(min: nil, max: nil, limit: nil)
62
+
63
+ expect(subject.check).to be_falsey
64
+
65
+ is_expected.to have_attributes(min: min_expected, max: max_expected, limit: max_expected)
66
+ end
67
+
68
+ it 'expect call reaction when check succeded' do
69
+ expect(memory).to receive(:bytes).and_return(rss)
70
+
71
+ skip_cycles(subject, check_cycle)
72
+ expect(subject.check).to be_falsey
73
+
74
+ expect(memory).to receive(:bytes).and_return(subject.limit + 1)
75
+ skip_cycles(subject, check_cycle)
76
+ expect(subject.check).to be_truthy
77
+ end
41
78
  end
42
79
  end
43
80
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: worker_killer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2.187852
4
+ version: 1.0.3.189098
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samoilenko Yuri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-28 00:00:00.000000000 Z
11
+ date: 2023-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: get_process_mem
@@ -171,15 +171,15 @@ signing_key:
171
171
  specification_version: 4
172
172
  summary: Kill any workers by memory and request counts or take custom reaction
173
173
  test_files:
174
- - spec/middleware_spec.rb
174
+ - spec/killer/signal_spec.rb
175
+ - spec/killer/delayed_job_spec.rb
176
+ - spec/killer/passenger_spec.rb
175
177
  - spec/killer_spec.rb
178
+ - spec/count_limiter_spec.rb
179
+ - spec/worker_killer_spec.rb
180
+ - spec/support/logger.rb
181
+ - spec/middleware_spec.rb
176
182
  - spec/spec_helper.rb
177
183
  - spec/delayed_job_plugin/oom_limiter_spec.rb
178
184
  - spec/delayed_job_plugin/jobs_limiter_spec.rb
179
- - spec/killer/passenger_spec.rb
180
- - spec/killer/signal_spec.rb
181
- - spec/killer/delayed_job_spec.rb
182
185
  - spec/memory_limiter_spec.rb
183
- - spec/support/logger.rb
184
- - spec/worker_killer_spec.rb
185
- - spec/count_limiter_spec.rb