sidekiq-worker-killer 0.4.0 → 0.5.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 +4 -4
- data/README.md +17 -2
- data/lib/sidekiq/worker_killer.rb +9 -2
- data/lib/sidekiq/worker_killer/version.rb +1 -1
- data/spec/sidekiq/worker_killer_spec.rb +38 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfc7e3a75eba6f95fd48ee2c0fa604cddad8328f
|
4
|
+
data.tar.gz: 367eb4d8380b612dad3300829962cdcad40509fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e26eae8384c0a43e2f57b792f094abb12b419ef58a47cfda9d2e42285ebfacf4ade437148cd20e742c5a6aaea9c1dc392e5272749aff2c1ad607e860325724a1
|
7
|
+
data.tar.gz: c347ad5878953ff5383508f0871d1beb12c1442970b2c2f6b4ff8b86a869002f75b928221506c176b395cf69b2419376e002340d70ecdfe82fb33f25c90c2d17
|
data/README.md
CHANGED
@@ -36,10 +36,25 @@ The following options can be overrided.
|
|
36
36
|
| Option | Defaults | Description |
|
37
37
|
| ------- | ------- | ----------- |
|
38
38
|
| max_rss | 0 MB (disabled) | max RSS in megabytes. Above this, shutdown will be triggered. |
|
39
|
-
| grace_time | 900 seconds | when shutdown is triggered, the Sidekiq process will not accept new job and wait at most 15 minutes for running jobs to finish. If Float::INFINITY specified, will wait forever |
|
39
|
+
| grace_time | 900 seconds | when shutdown is triggered, the Sidekiq process will not accept new job and wait at most 15 minutes for running jobs to finish. If Float::INFINITY specified, will wait forever. |
|
40
40
|
| shutdown_wait | 30 seconds | when the grace time expires, still running jobs get 30 seconds to terminate. After that, kill signal is triggered. |
|
41
41
|
| kill_signal | SIGKILL | Signal to use kill Sidekiq process if it doesn't terminate. |
|
42
|
-
| gc | true | Try to run garbage collection before Sidekiq process terminate in case of max_rss exceeded |
|
42
|
+
| gc | true | Try to run garbage collection before Sidekiq process terminate in case of max_rss exceeded. |
|
43
|
+
| skip_shutdown_if | Proc.new {false} | Executes a block of code after max_rss exceeds but before requesting shutdown. |
|
44
|
+
|
45
|
+
*skip_shutdown_if* is expected to return anything other than `false` or `nil` to skip shutdown.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'sidekiq/worker_killer'
|
49
|
+
|
50
|
+
Sidekiq.configure_server do |config|
|
51
|
+
config.server_middleware do |chain|
|
52
|
+
chain.add Sidekiq::WorkerKiller, max_rss: 480, skip_shutdown_if: ->(worker, job, queue) do
|
53
|
+
worker.to_s == 'LongWorker'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
```
|
43
58
|
|
44
59
|
## Development
|
45
60
|
|
@@ -15,16 +15,21 @@ class Sidekiq::WorkerKiller
|
|
15
15
|
@shutdown_wait = options.fetch(:shutdown_wait, 30)
|
16
16
|
@kill_signal = options.fetch(:kill_signal, "SIGKILL")
|
17
17
|
@gc = options.fetch(:gc, true)
|
18
|
+
@skip_shutdown = options.fetch(:skip_shutdown_if, Proc.new { false })
|
18
19
|
end
|
19
20
|
|
20
|
-
def call(
|
21
|
+
def call(worker, job, queue)
|
21
22
|
yield
|
22
23
|
# Skip if the max RSS is not exceeded
|
23
24
|
return unless @max_rss > 0
|
24
25
|
return unless current_rss > @max_rss
|
25
26
|
GC.start(full_mark: true, immediate_sweep: true) if @gc
|
26
27
|
return unless current_rss > @max_rss
|
27
|
-
|
28
|
+
if @skip_shutdown.respond_to?(:call) && @skip_shutdown.call(worker, job, queue)
|
29
|
+
warn "current RSS #{current_rss} exceeds maximum RSS #{@max_rss}, however shutdown will be ignored"
|
30
|
+
return
|
31
|
+
end
|
32
|
+
|
28
33
|
warn "current RSS #{current_rss} of #{identity} exceeds " \
|
29
34
|
"maximum RSS #{@max_rss}"
|
30
35
|
request_shutdown
|
@@ -45,6 +50,8 @@ class Sidekiq::WorkerKiller
|
|
45
50
|
warn "sending #{quiet_signal} to #{identity}"
|
46
51
|
signal(quiet_signal, pid)
|
47
52
|
|
53
|
+
sleep(5) # gives Sidekiq API 5 seconds to update ProcessSet
|
54
|
+
|
48
55
|
warn "shutting down #{identity} in #{@grace_time} seconds"
|
49
56
|
wait_job_finish_in_grace_time
|
50
57
|
|
@@ -4,6 +4,7 @@ describe Sidekiq::WorkerKiller do
|
|
4
4
|
|
5
5
|
before do
|
6
6
|
allow(subject).to receive(:warn) # silence "warn" logs
|
7
|
+
allow(subject).to receive(:sleep) # reduces tests running time
|
7
8
|
end
|
8
9
|
|
9
10
|
describe "#call" do
|
@@ -29,6 +30,43 @@ describe Sidekiq::WorkerKiller do
|
|
29
30
|
expect(GC).to receive(:start).with(full_mark: true, immediate_sweep: true)
|
30
31
|
subject.call(worker, job, queue){}
|
31
32
|
end
|
33
|
+
|
34
|
+
context "and skip_shutdown_if is given" do
|
35
|
+
subject{ described_class.new(max_rss: 2, skip_shutdown_if: skip_shutdown_proc) }
|
36
|
+
|
37
|
+
context "and skip_shutdown_if is a proc" do
|
38
|
+
let(:skip_shutdown_proc) { proc { |worker| true } }
|
39
|
+
it "should NOT request shutdown" do
|
40
|
+
expect(subject).not_to receive(:request_shutdown)
|
41
|
+
subject.call(worker, job, queue){}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "and skip_shutdown_if is a lambda" do
|
46
|
+
let(:skip_shutdown_proc) { ->(worker, job, queue) { true } }
|
47
|
+
it "should NOT request shutdown" do
|
48
|
+
expect(subject).not_to receive(:request_shutdown)
|
49
|
+
subject.call(worker, job, queue){}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "and skip_shutdown_if returns false" do
|
54
|
+
let(:skip_shutdown_proc) { proc { |worker, job, queue| false } }
|
55
|
+
it "should still request shutdown" do
|
56
|
+
expect(subject).to receive(:request_shutdown)
|
57
|
+
subject.call(worker, job, queue){}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "and skip_shutdown_if returns nil" do
|
62
|
+
let(:skip_shutdown_proc) { proc { |worker, job, queue| nil } }
|
63
|
+
it "should still request shutdown" do
|
64
|
+
expect(subject).to receive(:request_shutdown)
|
65
|
+
subject.call(worker, job, queue){}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
32
70
|
context "when gc is false" do
|
33
71
|
subject{ described_class.new(max_rss: 2, gc: false) }
|
34
72
|
it "should not call garbage collect" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-worker-killer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyrille Courtiere
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: get_process_mem
|