xpool 0.10.0 → 0.10.1
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.
- data/ChangeLog.txt +20 -0
- data/lib/xpool/process.rb +18 -9
- data/lib/xpool/version.rb +1 -1
- data/test/support/io_writer.rb +16 -4
- data/test/support/raiser.rb +5 -0
- data/test/xpool_process_test.rb +10 -0
- metadata +4 -4
data/ChangeLog.txt
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
== HEAD
|
|
2
|
+
- no longer log from trap(…) block.
|
|
3
|
+
the logger cannot log from within a trap block on Ruby2, so I've removed
|
|
4
|
+
logging when a subprocess gets a request to shutdown.
|
|
5
|
+
|
|
6
|
+
- call 'setup' on unit of work if defined.
|
|
7
|
+
'setup', if defined by a unit of work, is called just before a unit of work
|
|
8
|
+
is executed for the first time… useful if you need to create an environment
|
|
9
|
+
for the subprocess to operate in.
|
|
10
|
+
|
|
11
|
+
- resize & resize! no longer accepts a Range.
|
|
12
|
+
deprecated in the last release, support for a Range to either resize or
|
|
13
|
+
resize! is completely removed in this release. Please use a Fixnum instead.
|
|
14
|
+
|
|
15
|
+
== v0.10.1
|
|
16
|
+
- Restarted subprocesses inherit the message queue of their predecessor.
|
|
17
|
+
when a failed subprocess is restarted its message queue is inherited by its
|
|
18
|
+
replacement. Any messages it had waiting will be processed by the replacement
|
|
19
|
+
process.
|
|
20
|
+
|
|
1
21
|
== v0.10.0
|
|
2
22
|
- default to two subprocesses if CPU core count cannot be guessed.
|
|
3
23
|
Which is change from the old default of five.
|
data/lib/xpool/process.rb
CHANGED
|
@@ -4,6 +4,7 @@ class XPool::Process
|
|
|
4
4
|
# Returns an instance of XPool::Process
|
|
5
5
|
#
|
|
6
6
|
def initialize
|
|
7
|
+
reset
|
|
7
8
|
@id = spawn
|
|
8
9
|
end
|
|
9
10
|
|
|
@@ -115,25 +116,32 @@ class XPool::Process
|
|
|
115
116
|
@states[:backtrace]
|
|
116
117
|
end
|
|
117
118
|
|
|
119
|
+
#
|
|
120
|
+
# Restart the process. The current process shuts down(gracefully) and a new
|
|
121
|
+
# process replaces it. If the current process has failed the new process will
|
|
122
|
+
# inherit its message queue.
|
|
118
123
|
#
|
|
119
124
|
# @return [Fixnum]
|
|
120
125
|
# Returns the process ID of the new process.
|
|
121
126
|
#
|
|
122
127
|
def restart
|
|
123
|
-
|
|
128
|
+
_shutdown 'SIGUSR1', false
|
|
129
|
+
reset(false)
|
|
124
130
|
@id = spawn
|
|
125
131
|
end
|
|
126
132
|
|
|
127
133
|
private
|
|
128
|
-
def _shutdown(sig)
|
|
134
|
+
def _shutdown(sig, close_channels=true)
|
|
129
135
|
Process.kill sig, @id
|
|
130
136
|
Process.wait @id
|
|
131
137
|
rescue Errno::ECHILD, Errno::ESRCH
|
|
132
138
|
ensure
|
|
133
139
|
@states = {dead: true} unless failed?
|
|
134
140
|
@shutdown = true
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
if close_channels
|
|
142
|
+
@channel.close
|
|
143
|
+
@s_channel.close
|
|
144
|
+
end
|
|
137
145
|
end
|
|
138
146
|
|
|
139
147
|
def synchronize!
|
|
@@ -144,16 +152,17 @@ private
|
|
|
144
152
|
@states
|
|
145
153
|
end
|
|
146
154
|
|
|
147
|
-
def reset
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
def reset(new_channels = true)
|
|
156
|
+
if new_channels
|
|
157
|
+
@channel = IChannel.new Marshal
|
|
158
|
+
@s_channel = IChannel.new Marshal
|
|
159
|
+
end
|
|
150
160
|
@shutdown = false
|
|
151
161
|
@states = {}
|
|
152
162
|
@frequency = 0
|
|
153
163
|
end
|
|
154
164
|
|
|
155
165
|
def spawn
|
|
156
|
-
reset
|
|
157
166
|
fork do
|
|
158
167
|
trap :SIGUSR1 do
|
|
159
168
|
XPool.log "#{::Process.pid} got request to shutdown."
|
|
@@ -172,8 +181,8 @@ private
|
|
|
172
181
|
end
|
|
173
182
|
sleep 0.05
|
|
174
183
|
rescue Exception => e
|
|
175
|
-
XPool.log "#{::Process.pid} has failed."
|
|
176
184
|
@s_channel.put failed: true, dead: true, backtrace: e.backtrace
|
|
185
|
+
XPool.log "Process with ID '#{@id}' has failed."
|
|
177
186
|
raise e
|
|
178
187
|
ensure
|
|
179
188
|
if @shutdown_requested && !@channel.readable?
|
data/lib/xpool/version.rb
CHANGED
data/test/support/io_writer.rb
CHANGED
|
@@ -13,9 +13,21 @@ class IOWriter
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def wrote_to_disk?
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
if File.exist? @path
|
|
17
|
+
val = File.read(@path)
|
|
18
|
+
FileUtils.rm_rf @path
|
|
19
|
+
val == 'true'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class IOSetupWriter < IOWriter
|
|
25
|
+
def setup
|
|
26
|
+
File.open @path, 'w' do |f|
|
|
27
|
+
f.write 'true'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def run
|
|
20
32
|
end
|
|
21
33
|
end
|
data/test/support/raiser.rb
CHANGED
data/test/xpool_process_test.rb
CHANGED
|
@@ -8,6 +8,16 @@ class XPoolProcessTest < Test::Unit::TestCase
|
|
|
8
8
|
@process.shutdown!
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def test_resume_process_on_failed_process_queue
|
|
12
|
+
@process.schedule Raiser.new(0.1)
|
|
13
|
+
io_writers = Array.new(5) { IOWriter.new }
|
|
14
|
+
io_writers.each { |writer| @process.schedule writer }
|
|
15
|
+
until @process.failed?; sleep 0.1; end
|
|
16
|
+
@process.restart
|
|
17
|
+
sleep 0.5
|
|
18
|
+
io_writers.each { |io_writer| assert io_writer.wrote_to_disk? }
|
|
19
|
+
end
|
|
20
|
+
|
|
11
21
|
def test_busy_method
|
|
12
22
|
@process.schedule Sleeper.new(0.5)
|
|
13
23
|
sleep 0.1
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: xpool
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.10.
|
|
4
|
+
version: 0.10.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
12
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: ichannel
|
|
@@ -70,7 +70,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
70
70
|
version: '0'
|
|
71
71
|
segments:
|
|
72
72
|
- 0
|
|
73
|
-
hash: -
|
|
73
|
+
hash: -3457064609731373945
|
|
74
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
none: false
|
|
76
76
|
requirements:
|
|
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
79
79
|
version: '0'
|
|
80
80
|
segments:
|
|
81
81
|
- 0
|
|
82
|
-
hash: -
|
|
82
|
+
hash: -3457064609731373945
|
|
83
83
|
requirements: []
|
|
84
84
|
rubyforge_project:
|
|
85
85
|
rubygems_version: 1.8.23
|