spool 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/spool/configuration.rb +0 -1
- data/lib/spool/pool.rb +66 -39
- data/lib/spool/version.rb +1 -1
- data/lib/spool.rb +1 -0
- data/spec/pool_spec.rb +30 -30
- 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: ded6da3c7760ef6ba4bf10f1d20c836f69901c0b
|
4
|
+
data.tar.gz: 31597cc84078b8289b7fb93089531d29e233e626
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b172a8077738059e68bb160b60892355cfce88aabf6bc18c03eacba4c927aa936a36924093bc4b7a5d153eb107be287a65170bd1345f71f045d10a07c71129c
|
7
|
+
data.tar.gz: bf20887bd046790fb8ffc65fd803dc28b953283c00f02d075ca210c1b3389a8d45b7e744127d19d0d07ec2d9fc25a80e421b93fe423edc7853cf1687d4c07551
|
data/lib/spool/configuration.rb
CHANGED
data/lib/spool/pool.rb
CHANGED
@@ -13,11 +13,12 @@ module Spool
|
|
13
13
|
TTOU: :decr
|
14
14
|
}
|
15
15
|
|
16
|
-
attr_reader :configuration, :
|
16
|
+
attr_reader :configuration, :working_processes, :zombie_processes
|
17
17
|
|
18
18
|
def initialize(configuration=nil, &block)
|
19
19
|
@configuration = configuration || DSL.configure(&block)
|
20
|
-
@
|
20
|
+
@working_processes = []
|
21
|
+
@zombie_processes = Set.new
|
21
22
|
@running = false
|
22
23
|
@actions_queue = []
|
23
24
|
end
|
@@ -30,6 +31,10 @@ module Spool
|
|
30
31
|
!running?
|
31
32
|
end
|
32
33
|
|
34
|
+
def all_processes
|
35
|
+
working_processes + zombie_processes.to_a
|
36
|
+
end
|
37
|
+
|
33
38
|
[:incr, :decr, :reload, :restart, :stop, :stop!].each do |method|
|
34
39
|
define_method method do |*args|
|
35
40
|
actions_queue.push(name: "_#{method}".to_sym, args: args)
|
@@ -45,10 +50,10 @@ module Spool
|
|
45
50
|
File.write configuration.pid_file, Process.pid if configuration.pid_file
|
46
51
|
|
47
52
|
configuration.processes.times.map do
|
48
|
-
|
53
|
+
working_processes << Spawner.spawn(configuration)
|
49
54
|
end
|
50
55
|
|
51
|
-
logger.info(self.class) { "SPOOL START
|
56
|
+
logger.info(self.class) { "SPOOL START => #{format_processes}" }
|
52
57
|
|
53
58
|
while running?
|
54
59
|
action = actions_queue.pop
|
@@ -69,6 +74,7 @@ module Spool
|
|
69
74
|
|
70
75
|
private
|
71
76
|
|
77
|
+
attr_writer :working_processes, :zombie_processes
|
72
78
|
attr_reader :actions_queue
|
73
79
|
|
74
80
|
def handle_signals
|
@@ -81,36 +87,31 @@ module Spool
|
|
81
87
|
end
|
82
88
|
|
83
89
|
def check_status
|
84
|
-
|
85
|
-
|
86
|
-
to_restart = processes.select(&configuration.restart_condition)
|
87
|
-
logger.info(self.class) {"Restart condition successful in child processes: #{to_restart.map(&:pid)}"} if to_restart.any?
|
88
|
-
stop_processes to_restart
|
90
|
+
clear_dead_processes
|
89
91
|
|
90
|
-
|
91
|
-
|
92
|
+
check_processes_to_restart
|
93
|
+
|
94
|
+
if configuration.processes > all_processes_count
|
95
|
+
logger.info(self.class) { "Initializing new children. Current State => #{format_processes}" }
|
92
96
|
|
93
|
-
(configuration.processes -
|
94
|
-
|
97
|
+
(configuration.processes - all_processes_count).times do
|
98
|
+
working_processes << Spawner.spawn(configuration)
|
95
99
|
end
|
96
100
|
|
97
|
-
logger.info(self.class) { "New children: #{
|
98
|
-
elsif configuration.processes <
|
99
|
-
|
101
|
+
logger.info(self.class) { "New children: #{working_processes.last.pid}" }
|
102
|
+
elsif configuration.processes < working_processes.count
|
103
|
+
count_to_kill = working_processes.count - configuration.processes
|
104
|
+
logger.info(self.class) { "Killing #{count_to_kill} children. Current state => #{format_processes}" }
|
100
105
|
|
101
|
-
|
102
|
-
stop_processes list
|
103
|
-
wait_for_stopped list
|
104
|
-
list.each { |p| processes.delete p }
|
106
|
+
stop_processes working_processes.take(count_to_kill)
|
105
107
|
|
106
|
-
logger.info(self.class) { "After
|
108
|
+
logger.info(self.class) { "After killing childers. Current State => #{format_processes}" }
|
107
109
|
end
|
108
110
|
|
109
111
|
rescue Exception => e
|
110
112
|
log_error e
|
111
113
|
end
|
112
114
|
|
113
|
-
|
114
115
|
def _incr(count=1)
|
115
116
|
configuration.processes += count
|
116
117
|
end
|
@@ -126,14 +127,14 @@ module Spool
|
|
126
127
|
|
127
128
|
def _restart
|
128
129
|
logger.info(self.class) { "RESTART" }
|
129
|
-
stop_processes
|
130
|
+
stop_processes working_processes
|
130
131
|
end
|
131
132
|
|
132
133
|
def _stop(timeout=0)
|
133
134
|
logger.info(self.class) { "SPOOL STOP" }
|
134
135
|
|
135
|
-
stop_processes
|
136
|
-
Timeout.timeout(timeout) { wait_for_stopped
|
136
|
+
stop_processes working_processes
|
137
|
+
Timeout.timeout(timeout) { wait_for_stopped all_processes }
|
137
138
|
rescue Timeout::Error
|
138
139
|
logger.error(self.class) { "ERROR IN SPOOL STOP. Timeout error" }
|
139
140
|
ensure
|
@@ -142,23 +143,20 @@ module Spool
|
|
142
143
|
end
|
143
144
|
|
144
145
|
def _stop!
|
145
|
-
logger.info(self.class) { "SPOOL STOP! kill
|
146
|
+
logger.info(self.class) { "SPOOL STOP! Going to kill => #{format_processes}" }
|
146
147
|
|
147
|
-
|
148
|
+
all_processes.each do |p|
|
148
149
|
begin
|
149
|
-
p
|
150
|
+
send_signal_to(p, configuration.kill_signal) if p.alive?
|
150
151
|
rescue Datacenter::Shell::CommandError => e
|
151
|
-
|
152
|
-
log_error e
|
153
|
-
else
|
154
|
-
logger.info(self.class) { "Signal KILL was sent to #{p.pid} but process was already dead" }
|
155
|
-
end
|
152
|
+
log_error e
|
156
153
|
end
|
157
154
|
end
|
158
155
|
|
159
|
-
wait_for_stopped
|
156
|
+
wait_for_stopped all_processes
|
160
157
|
|
161
|
-
|
158
|
+
working_processes.clear
|
159
|
+
zombie_processes.clear
|
162
160
|
|
163
161
|
File.delete configuration.pid_file if File.exist? configuration.pid_file
|
164
162
|
@running = false
|
@@ -167,20 +165,45 @@ module Spool
|
|
167
165
|
def stop_processes(processes_list)
|
168
166
|
processes_list.each do |p|
|
169
167
|
begin
|
170
|
-
|
171
|
-
p
|
168
|
+
send_signal_to p, configuration.stop_signal
|
169
|
+
zombie_processes << p
|
172
170
|
rescue Exception => e
|
173
171
|
log_error e
|
174
172
|
end
|
175
173
|
end
|
174
|
+
|
175
|
+
working_processes.delete_if{ |p| zombie_processes.include? p }
|
176
176
|
end
|
177
177
|
|
178
|
-
def wait_for_stopped(
|
179
|
-
while
|
178
|
+
def wait_for_stopped(processes_list)
|
179
|
+
while processes_list.any?(&:alive?)
|
180
180
|
sleep 0.01
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
184
|
+
def check_processes_to_restart
|
185
|
+
to_restart = working_processes.select(&configuration.restart_condition)
|
186
|
+
|
187
|
+
if to_restart.any?
|
188
|
+
logger.info(self.class) {"Restart condition successful in child processes: #{to_restart.map(&:pid)}"}
|
189
|
+
stop_processes to_restart
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def send_signal_to(process, signal)
|
194
|
+
logger.info(self.class) { "Going to send signal #{signal} to process #{process.pid}" }
|
195
|
+
process.send_signal signal
|
196
|
+
end
|
197
|
+
|
198
|
+
def clear_dead_processes
|
199
|
+
working_processes.delete_if { |p| !p.alive? }
|
200
|
+
zombie_processes.delete_if { |p| !p.alive? }
|
201
|
+
end
|
202
|
+
|
203
|
+
def all_processes_count
|
204
|
+
working_processes.count + zombie_processes.count
|
205
|
+
end
|
206
|
+
|
184
207
|
def logger
|
185
208
|
configuration.logger
|
186
209
|
end
|
@@ -197,6 +220,10 @@ module Spool
|
|
197
220
|
end.join("\n")
|
198
221
|
end
|
199
222
|
|
223
|
+
def format_processes
|
224
|
+
"Working Processes: #{working_processes.map(&:pid)}, Zombie Processes: #{zombie_processes.map(&:pid)}"
|
225
|
+
end
|
226
|
+
|
200
227
|
end
|
201
228
|
|
202
229
|
end
|
data/lib/spool/version.rb
CHANGED
data/lib/spool.rb
CHANGED
data/spec/pool_spec.rb
CHANGED
@@ -18,7 +18,7 @@ describe Spool::Pool do
|
|
18
18
|
@pool = Spool::Pool.new(&block).tap do |pool|
|
19
19
|
t = Thread.new { pool.start }
|
20
20
|
t.abort_on_exception = true
|
21
|
-
while pool.
|
21
|
+
while pool.all_processes.count < pool.configuration.processes
|
22
22
|
sleep 0.01
|
23
23
|
end
|
24
24
|
end
|
@@ -40,10 +40,10 @@ describe Spool::Pool do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
pool.must_be :running?
|
43
|
-
pool.
|
44
|
-
pool.
|
43
|
+
pool.all_processes.count.must_equal 1
|
44
|
+
pool.all_processes[0].must_be :alive?
|
45
45
|
|
46
|
-
process = pool.
|
46
|
+
process = pool.all_processes[0]
|
47
47
|
pool.stop
|
48
48
|
|
49
49
|
while pool.running?
|
@@ -51,7 +51,7 @@ describe Spool::Pool do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
pool.must_be :stopped?
|
54
|
-
pool.
|
54
|
+
pool.all_processes.must_be_empty
|
55
55
|
process.wont_be :alive?
|
56
56
|
end
|
57
57
|
|
@@ -62,10 +62,10 @@ describe Spool::Pool do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
pool.must_be :running?
|
65
|
-
pool.
|
66
|
-
pool.
|
65
|
+
pool.all_processes.count.must_equal 1
|
66
|
+
pool.all_processes[0].must_be :alive?
|
67
67
|
|
68
|
-
process = pool.
|
68
|
+
process = pool.all_processes[0]
|
69
69
|
|
70
70
|
pool.stop!
|
71
71
|
|
@@ -74,7 +74,7 @@ describe Spool::Pool do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
pool.must_be :stopped?
|
77
|
-
pool.
|
77
|
+
pool.all_processes.must_be_empty
|
78
78
|
process.wont_be :alive?
|
79
79
|
end
|
80
80
|
|
@@ -84,18 +84,18 @@ describe Spool::Pool do
|
|
84
84
|
command 'ruby -e "loop do; sleep 1; end"'
|
85
85
|
end
|
86
86
|
|
87
|
-
original_process = pool.
|
87
|
+
original_process = pool.all_processes[0]
|
88
88
|
original_process.send_signal :KILL
|
89
89
|
|
90
90
|
begin
|
91
91
|
sleep SLEEP_TIME
|
92
|
-
new_pid = pool.
|
92
|
+
new_pid = pool.all_processes.any? ? pool.all_processes[0].pid : original_process.pid
|
93
93
|
end while original_process.pid == new_pid
|
94
94
|
|
95
95
|
original_process.wont_be :alive?
|
96
96
|
|
97
|
-
pool.
|
98
|
-
pool.
|
97
|
+
pool.all_processes.count.must_equal 1
|
98
|
+
pool.all_processes[0].must_be :alive?
|
99
99
|
end
|
100
100
|
|
101
101
|
it 'Restart processes' do
|
@@ -105,18 +105,18 @@ describe Spool::Pool do
|
|
105
105
|
stop_signal :TERM
|
106
106
|
end
|
107
107
|
|
108
|
-
pool.
|
108
|
+
pool.all_processes.count.must_equal 2
|
109
109
|
|
110
|
-
original_pids = pool.
|
110
|
+
original_pids = pool.all_processes.map(&:pid)
|
111
111
|
|
112
112
|
pool.restart
|
113
113
|
|
114
114
|
begin
|
115
115
|
sleep SLEEP_TIME
|
116
|
-
new_pids = (pool.
|
116
|
+
new_pids = (pool.all_processes.count == 2) ? pool.all_processes.map(&:pid) : original_pids
|
117
117
|
end until (original_pids & new_pids).empty?
|
118
118
|
|
119
|
-
pool.
|
119
|
+
pool.all_processes.each { |p| p.must_be :alive?}
|
120
120
|
end
|
121
121
|
|
122
122
|
it 'Stop with timeout' do
|
@@ -126,7 +126,7 @@ describe Spool::Pool do
|
|
126
126
|
stop_signal :QUIT
|
127
127
|
end
|
128
128
|
|
129
|
-
process = pool.
|
129
|
+
process = pool.all_processes[0]
|
130
130
|
|
131
131
|
Benchmark.realtime do
|
132
132
|
pool.stop 0.1
|
@@ -136,7 +136,7 @@ describe Spool::Pool do
|
|
136
136
|
end.must_be :<, 1
|
137
137
|
|
138
138
|
pool.must_be :stopped?
|
139
|
-
pool.
|
139
|
+
pool.all_processes.must_be_empty
|
140
140
|
process.wont_be :alive?
|
141
141
|
end
|
142
142
|
|
@@ -146,11 +146,11 @@ describe Spool::Pool do
|
|
146
146
|
command 'ruby -e "loop do; sleep 1; end"'
|
147
147
|
end
|
148
148
|
|
149
|
-
pool.
|
149
|
+
pool.all_processes.count.must_equal 1
|
150
150
|
|
151
151
|
pool.incr 2
|
152
152
|
|
153
|
-
assert_with_timeout(1) { pool.
|
153
|
+
assert_with_timeout(1) { pool.all_processes.count == 3 }
|
154
154
|
end
|
155
155
|
|
156
156
|
it 'Decrease processes' do
|
@@ -160,11 +160,11 @@ describe Spool::Pool do
|
|
160
160
|
stop_signal :TERM
|
161
161
|
end
|
162
162
|
|
163
|
-
pool.
|
163
|
+
pool.all_processes.count.must_equal 3
|
164
164
|
|
165
165
|
pool.decr 2
|
166
166
|
|
167
|
-
assert_with_timeout(1) { pool.
|
167
|
+
assert_with_timeout(1) { pool.all_processes.count == 1 }
|
168
168
|
end
|
169
169
|
|
170
170
|
it 'Change process when satisfied stop condition' do
|
@@ -187,18 +187,18 @@ describe Spool::Pool do
|
|
187
187
|
stop_signal :TERM
|
188
188
|
end
|
189
189
|
|
190
|
-
original_process = pool.
|
190
|
+
original_process = pool.all_processes[0]
|
191
191
|
|
192
192
|
begin
|
193
193
|
sleep SLEEP_TIME
|
194
|
-
new_pid = pool.
|
194
|
+
new_pid = pool.all_processes.any? ? pool.all_processes[0].pid : original_process.pid
|
195
195
|
end while original_process.pid == new_pid
|
196
196
|
|
197
197
|
text_file = File.read(file_name)
|
198
198
|
File.delete(file_name)
|
199
199
|
|
200
200
|
text_file.must_equal 'Finished'
|
201
|
-
pool.
|
201
|
+
pool.all_processes.count.must_equal 1
|
202
202
|
end
|
203
203
|
|
204
204
|
it 'Reload config' do
|
@@ -208,19 +208,19 @@ describe Spool::Pool do
|
|
208
208
|
pool = Spool::Pool.new(config).tap do |pool|
|
209
209
|
t = Thread.new { pool.start }
|
210
210
|
t.abort_on_exception = true
|
211
|
-
while pool.
|
211
|
+
while pool.all_processes.count < pool.configuration.processes
|
212
212
|
end
|
213
213
|
end
|
214
214
|
|
215
|
-
pool.
|
215
|
+
pool.all_processes.count.must_equal 1
|
216
216
|
|
217
217
|
pool.incr 1
|
218
218
|
|
219
|
-
assert_with_timeout(1) { pool.
|
219
|
+
assert_with_timeout(1) { pool.all_processes.count == 2 }
|
220
220
|
|
221
221
|
pool.reload
|
222
222
|
|
223
|
-
assert_with_timeout(1) { pool.
|
223
|
+
assert_with_timeout(1) { pool.all_processes.count == 1 }
|
224
224
|
|
225
225
|
pool.stop!
|
226
226
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: datacenter
|