worker_killer 1.0.5.213889 → 1.0.5.213977

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d0558051a55e944e97bb26729239a97d7f150fb37885af8761246f78db4e280
4
- data.tar.gz: 417bb8c4f0c4818d4e2a19ad4f2cb8cc5e3ca82621b925c81c2e4b33102803fb
3
+ metadata.gz: 2ac9af870733f50ff006c5a31d9c3030342d76ff3208b8e4193a2407ad8f264c
4
+ data.tar.gz: c222a1cada623f95f8668e61d15e4f32fa986fdf799572e1937365919bc651d4
5
5
  SHA512:
6
- metadata.gz: 855f6852cb2c7c8115388038f07d234958a6183c008d21b28ad8867a34a53dcfd713f34645c1b0f435fafc67f5f7ad0c1272b7b4f94f2d91b170ca91c0f97133
7
- data.tar.gz: 8699bc63da513186e47cb1ef626f732e61cfe7a603231370223cbcea5ec3b6d8897a314ed5fe8dee9a23765822b4c20aa43ddc6fda7b02bb775f01aa1f838a7e
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
- def initialize **kwrags
6
- super
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 do_kill(sig, pid, alive_sec, **_params)
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.213889
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