Class: WorkerKiller::Middleware
- Inherits:
-
Object
- Object
- WorkerKiller::Middleware
show all
- Defined in:
- lib/worker_killer/middleware.rb
Defined Under Namespace
Classes: OOMLimiter, RequestsLimiter
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#call(env) ⇒ Object
-
#call_with_inhibition(env, path_info, &after) ⇒ Object
-
#default_kill(l, k) ⇒ Object
-
#inihibit(_path_info) ⇒ Object
-
#initialize(app, killer:, klass:, interval: 10, inhibitions: [], reaction: nil, **opts) ⇒ Middleware
constructor
inhibitions - список адресов, которые будут времнно блокировать перезапуск воркеров: Rails.application.config.middleware.insert_before( Rack::Sendfile, WorkerKiller::Middleware::RequestsLimiter, killer:, min: 2, max: 3, inhibitions: ['/test'] ).
-
#logger ⇒ Object
-
#react ⇒ Object
-
#release ⇒ Object
-
#wrap_rack_response_body(rack_response_body, &after) ⇒ Object
Constructor Details
#initialize(app, killer:, klass:, interval: 10, inhibitions: [], reaction: nil, **opts) ⇒ Middleware
inhibitions - список адресов, которые будут времнно блокировать перезапуск воркеров:
Rails.application.config.middleware.insert_before(
Rack::Sendfile,
WorkerKiller::Middleware::RequestsLimiter, killer:, min: 2, max: 3, inhibitions: ['/test']
)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# File 'lib/worker_killer/middleware.rb', line 15
def initialize(app, killer:, klass:, interval: 10, inhibitions: [], reaction: nil, **opts)
@app = app
@killer = killer
@interval = interval
@inhibitions = inhibitions.dup.freeze
@reaction = reaction || method(:default_kill)
@limiter = klass.new(**opts)
@last_reacted_at = 0.0
@inhibited = 0
@delayed_reaction = nil
end
|
Instance Attribute Details
#inhibitions ⇒ Object
Returns the value of attribute inhibitions.
7
8
9
|
# File 'lib/worker_killer/middleware.rb', line 7
def inhibitions
@inhibitions
end
|
#interval ⇒ Object
Returns the value of attribute interval.
7
8
9
|
# File 'lib/worker_killer/middleware.rb', line 7
def interval
@interval
end
|
#killer ⇒ Object
Returns the value of attribute killer.
7
8
9
|
# File 'lib/worker_killer/middleware.rb', line 7
def killer
@killer
end
|
#limiter ⇒ Object
Returns the value of attribute limiter.
7
8
9
|
# File 'lib/worker_killer/middleware.rb', line 7
def limiter
@limiter
end
|
#reaction ⇒ Object
Returns the value of attribute reaction.
7
8
9
|
# File 'lib/worker_killer/middleware.rb', line 7
def reaction
@reaction
end
|
Instance Method Details
#call(env) ⇒ Object
30
31
32
33
34
35
36
37
38
39
40
41
42
|
# File 'lib/worker_killer/middleware.rb', line 30
def call(env)
if (path_info = env['PATH_INFO']) && inhibitions.any?{|i| path_info[i] }
call_with_inhibition(env, path_info) do
react if limiter.check
end
else
@app.call(env).tap do
react if limiter.check
end
end
end
|
#call_with_inhibition(env, path_info, &after) ⇒ Object
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
# File 'lib/worker_killer/middleware.rb', line 44
def call_with_inhibition(env, path_info, &after)
inihibit(path_info)
rack_response = nil
begin
rack_response = @app.call(env)
rescue Exception
release
raise
end
if rack_response[2].respond_to?(:each)
rack_response[2] = wrap_rack_response_body(rack_response[2], &after)
else
release after.call
end
rack_response
end
|
#default_kill(l, k) ⇒ Object
92
93
94
|
# File 'lib/worker_killer/middleware.rb', line 92
def default_kill(l, k)
k.kill(l.started_at)
end
|
#inihibit(_path_info) ⇒ Object
96
97
98
|
# File 'lib/worker_killer/middleware.rb', line 96
def inihibit(_path_info)
@inhibited += 1
end
|
#react ⇒ Object
80
81
82
83
84
85
86
87
88
89
90
|
# File 'lib/worker_killer/middleware.rb', line 80
def react
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
return if now - @last_reacted_at < @interval
@last_reacted_at = now
if @inhibited > 0
@delayed_reaction = -> { reaction.call(limiter, killer) }
else
reaction.call(limiter, killer)
end
end
|
#release ⇒ Object
100
101
102
103
104
105
106
107
|
# File 'lib/worker_killer/middleware.rb', line 100
def release
return unless ((@inhibited -= 1) == 0) && @delayed_reaction
@delayed_reaction.tap do |cb|
@delayed_reaction = nil
cb.call
end
end
|
#wrap_rack_response_body(rack_response_body, &after) ⇒ Object
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/worker_killer/middleware.rb', line 68
def wrap_rack_response_body(rack_response_body, &after)
Enumerator.new do |y|
rack_response_body.each {|chunk| y << chunk }
rack_response_body.close if rack_response_body.respond_to?(:close)
release after.call
end
end
|