worker_killer 1.0.5.213889 → 1.0.5.213977
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/lib/worker_killer/killer/puma.rb +32 -3
- data/lib/worker_killer/puma/plugin/worker_killer.rb +104 -0
- data/lib/worker_killer/puma_plugin.rb +58 -0
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ac9af870733f50ff006c5a31d9c3030342d76ff3208b8e4193a2407ad8f264c
|
|
4
|
+
data.tar.gz: c222a1cada623f95f8668e61d15e4f32fa986fdf799572e1937365919bc651d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88918e5de623c64691e96fbfc4f34b6eb19669e3f370be011eed996ef6e9a13aee61997b66adfae929e39cb685396557c3802d9a00dcb0ebef0d54e5cf1193fb
|
|
7
|
+
data.tar.gz: bdb4e2fafb1da70554c3b73284538695bfd918b1b516a9a24f477b02056d721b69745f4ecfe6bfde044fb90815fa55f7178c08c33d9cfd283420754d0175ee69
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
|
|
1
3
|
module ::WorkerKiller
|
|
2
4
|
module Killer
|
|
3
5
|
class Puma < ::WorkerKiller::Killer::Base
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
attr_accessor :type, :plugin_path, :num
|
|
8
|
+
|
|
9
|
+
def initialize(type: :phased, path: nil, num: nil, **kwargs)
|
|
10
|
+
super(**kwargs)
|
|
11
|
+
@type = type
|
|
12
|
+
@plugin_path = path
|
|
13
|
+
@num = num
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def do_kill(sig, pid, alive_sec, **params)
|
|
17
|
+
if @type == :phased
|
|
18
|
+
do_phased_kill(sig, pid, alive_sec, **params)
|
|
19
|
+
elsif @type == :plugin
|
|
20
|
+
do_plugin_kill(sig, pid, alive_sec, **params)
|
|
21
|
+
end
|
|
7
22
|
end
|
|
8
23
|
|
|
9
|
-
def
|
|
24
|
+
def do_phased_kill(sig, pid, alive_sec, **_params)
|
|
10
25
|
cmd = 'pumactl phased-restart'
|
|
11
26
|
|
|
12
27
|
if sig == :KILL
|
|
@@ -27,6 +42,20 @@ module ::WorkerKiller
|
|
|
27
42
|
end
|
|
28
43
|
end
|
|
29
44
|
|
|
45
|
+
def do_plugin_kill(sig, pid, alive_sec, **_params)
|
|
46
|
+
if sig == :KILL
|
|
47
|
+
logger.error "#{self} force to kill self (pid: #{pid}) alive: #{alive_sec} sec (trial #{kill_attempts})"
|
|
48
|
+
Process.kill sig, pid
|
|
49
|
+
return
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
logger.warn "#{self} send #{num} to Puma Plugin (pid: #{pid}) alive: #{alive_sec} sec (trial #{kill_attempts})"
|
|
53
|
+
|
|
54
|
+
Socket.unix(plugin_path) do |sock|
|
|
55
|
+
sock.puts num.to_s
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
30
59
|
end
|
|
31
60
|
end
|
|
32
61
|
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
require 'puma/plugin'
|
|
3
|
+
require 'active_support/notifications'
|
|
4
|
+
|
|
5
|
+
require 'worker_killer/killer'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module WorkerKiller
|
|
11
|
+
module Puma
|
|
12
|
+
module Plugin
|
|
13
|
+
# Puma requires such plugin name and path :(
|
|
14
|
+
class WorkerKiller
|
|
15
|
+
|
|
16
|
+
def initialize(launcher, path)
|
|
17
|
+
@runner = launcher.instance_variable_get('@runner')
|
|
18
|
+
|
|
19
|
+
@thread = Thread.new do
|
|
20
|
+
Socket.unix_server_loop(path) do |sock, _client_addrinfo|
|
|
21
|
+
if (line = sock.gets)
|
|
22
|
+
worker_num = Integer(line.strip)
|
|
23
|
+
if (worker = find_worker(worker_num))
|
|
24
|
+
log "Killing worker #{worker_num}"
|
|
25
|
+
worker.term!
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
rescue StandardError => e
|
|
29
|
+
log("Exception: #{e.inspect}")
|
|
30
|
+
ensure
|
|
31
|
+
sock.close
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def find_worker(worker_num)
|
|
37
|
+
worker = @runner.worker_at(worker_num)
|
|
38
|
+
unless worker
|
|
39
|
+
log "Unknown worker index: #{worker_num.inspect}. Skipping."
|
|
40
|
+
return nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
unless worker.booted?
|
|
44
|
+
log "Worker #{worker_num.inspect} is not booted yet. Skipping."
|
|
45
|
+
return nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if worker.term?
|
|
49
|
+
log "Worker #{worker_num.inspect} already terminating. Skipping."
|
|
50
|
+
return nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
worker
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def log(msg)
|
|
57
|
+
warn("#{self.class}: #{msg}")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
Puma::Plugin.create do
|
|
66
|
+
attr_reader :path
|
|
67
|
+
|
|
68
|
+
def config(c)
|
|
69
|
+
c.on_worker_boot do |num|
|
|
70
|
+
|
|
71
|
+
if @killer
|
|
72
|
+
puts "ON OTHER WORKER BOOT: #{num}"
|
|
73
|
+
@killer.num = num
|
|
74
|
+
else
|
|
75
|
+
puts "ON MAIN WORKER BOOT: #{num}"
|
|
76
|
+
::ActiveSupport::Notifications.subscribe 'worker_killer.initialize' do |*eargs|
|
|
77
|
+
@killer = ::WorkerKiller::Killer::Puma.new(num: num, path: path, type: :plugin)
|
|
78
|
+
puts "ON WORKER BOOT INIT:#{num}"
|
|
79
|
+
event = ActiveSupport::Notifications::Event.new(*eargs)
|
|
80
|
+
config = event.payload[:config]
|
|
81
|
+
|
|
82
|
+
@register_killer&.call(self, config, @killer)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def start(launcher)
|
|
89
|
+
@path = File.join('tmp', "puma_worker_killer_#{Process.pid}.socket")
|
|
90
|
+
|
|
91
|
+
launcher.events.on_booted do
|
|
92
|
+
@controller ||= WorkerKiller::Puma::Plugin::WorkerKiller.new(launcher, path)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def configure(&block)
|
|
97
|
+
self.instance_eval(&block)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def register_killer(&block)
|
|
101
|
+
@register_killer = block
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'worker_killer/memory_limiter'
|
|
2
|
+
require 'worker_killer/count_limiter'
|
|
3
|
+
require 'puma/plugin'
|
|
4
|
+
|
|
5
|
+
Puma::Plugin.create do
|
|
6
|
+
|
|
7
|
+
module WorkerKiller
|
|
8
|
+
class PumaPlugin
|
|
9
|
+
|
|
10
|
+
attr_reader :limiter, :killer, :reaction
|
|
11
|
+
|
|
12
|
+
def initialize(klass:, killer:, reaction: nil, **opts)
|
|
13
|
+
@killer = killer
|
|
14
|
+
|
|
15
|
+
@reaction = reaction || proc do |l, k, dj|
|
|
16
|
+
k.kill(l.started_at, dj: dj)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@limiter = klass.new(**opts)
|
|
20
|
+
@time_to_burn = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def new(lifecycle = Delayed::Worker.lifecycle, *_args)
|
|
24
|
+
configure_lifecycle(lifecycle)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def configure_lifecycle(lifecycle)
|
|
28
|
+
# Count condition after every job
|
|
29
|
+
lifecycle.after(:perform) do |worker, *_args|
|
|
30
|
+
@time_to_burn ||= limiter.check
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Stop execution only after whole loop completed
|
|
34
|
+
lifecycle.after(:loop) do |worker, *_args|
|
|
35
|
+
@time_to_burn ||= limiter.check
|
|
36
|
+
reaction.call(limiter, killer, worker) if @time_to_burn
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class JobsLimiter < ::WorkerKiller::PumaPlugin
|
|
41
|
+
|
|
42
|
+
def initialize(**opts)
|
|
43
|
+
super(klass: ::WorkerKiller::CountLimiter, **opts)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class OOMLimiter < ::WorkerKiller::PumaPlugin
|
|
49
|
+
|
|
50
|
+
def initialize(**opts)
|
|
51
|
+
super(klass: ::WorkerKiller::MemoryLimiter, **opts)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: worker_killer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.5.
|
|
4
|
+
version: 1.0.5.213977
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samoilenko Yuri
|
|
@@ -135,6 +135,8 @@ files:
|
|
|
135
135
|
- lib/worker_killer/killer/signal.rb
|
|
136
136
|
- lib/worker_killer/memory_limiter.rb
|
|
137
137
|
- lib/worker_killer/middleware.rb
|
|
138
|
+
- lib/worker_killer/puma/plugin/worker_killer.rb
|
|
139
|
+
- lib/worker_killer/puma_plugin.rb
|
|
138
140
|
- lib/worker_killer/version.rb
|
|
139
141
|
- spec/count_limiter_spec.rb
|
|
140
142
|
- spec/delayed_job_plugin/jobs_limiter_spec.rb
|
|
@@ -173,16 +175,16 @@ signing_key:
|
|
|
173
175
|
specification_version: 4
|
|
174
176
|
summary: Kill any workers by memory and request counts or take custom reaction
|
|
175
177
|
test_files:
|
|
176
|
-
- spec/killer/signal_spec.rb
|
|
177
|
-
- spec/killer/puma_spec.rb
|
|
178
|
-
- spec/killer/delayed_job_spec.rb
|
|
179
|
-
- spec/killer/passenger_spec.rb
|
|
180
|
-
- spec/killer_spec.rb
|
|
181
|
-
- spec/count_limiter_spec.rb
|
|
182
|
-
- spec/worker_killer_spec.rb
|
|
183
|
-
- spec/support/logger.rb
|
|
184
178
|
- spec/middleware_spec.rb
|
|
179
|
+
- spec/killer_spec.rb
|
|
185
180
|
- spec/spec_helper.rb
|
|
186
181
|
- spec/delayed_job_plugin/oom_limiter_spec.rb
|
|
187
182
|
- spec/delayed_job_plugin/jobs_limiter_spec.rb
|
|
183
|
+
- spec/killer/passenger_spec.rb
|
|
184
|
+
- spec/killer/puma_spec.rb
|
|
185
|
+
- spec/killer/signal_spec.rb
|
|
186
|
+
- spec/killer/delayed_job_spec.rb
|
|
188
187
|
- spec/memory_limiter_spec.rb
|
|
188
|
+
- spec/support/logger.rb
|
|
189
|
+
- spec/worker_killer_spec.rb
|
|
190
|
+
- spec/count_limiter_spec.rb
|