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