process_pool 0.1.2 → 0.1.3
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/Gemfile +1 -0
- data/TODO +12 -0
- data/VERSION +1 -1
- data/lib/anonymous_extension.rb +20 -0
- data/lib/base_worker_extension.rb +35 -0
- data/lib/init.rb +2 -0
- data/lib/process_pool.rb +26 -3
- data/lib/simple_queue.rb +8 -4
- data/process_pool.gemspec +10 -4
- data/test/anonymous_extension_test.rb +41 -0
- data/test/process_pool_test.rb +212 -1
- metadata +8 -2
data/Gemfile
CHANGED
data/TODO
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Extensions stuff:
|
2
|
+
- around extensions
|
3
|
+
- handling :stop
|
4
|
+
- helpers for anonymous extensions
|
5
|
+
- a couple of generic extensions:
|
6
|
+
- restarting active record connections on worker startup
|
7
|
+
- benchmarking
|
8
|
+
- restarting failed tasks
|
9
|
+
|
10
|
+
Queue:
|
11
|
+
- posix shared memory or message queue backend
|
12
|
+
- redis backend
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), 'init')
|
2
|
+
|
3
|
+
class AnonymousExtension < BaseWorkerExtension
|
4
|
+
|
5
|
+
SUPPORTED_EXTENSION_METHODS = [:before, :after, :around, :startup, :shutdown]
|
6
|
+
|
7
|
+
def initialize(method, &block)
|
8
|
+
raise ArgumentError.new("Unknown method: #{method}") unless SUPPORTED_EXTENSION_METHODS.include?(method)
|
9
|
+
|
10
|
+
@method = method
|
11
|
+
@block = lambda(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
SUPPORTED_EXTENSION_METHODS.each do |method_name|
|
15
|
+
define_method(method_name) do |*args|
|
16
|
+
@block.call(*args) if method_name == @method
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# base class for process pool extensions
|
2
|
+
#
|
3
|
+
# it is not required that the extensions inherit from this class,
|
4
|
+
# it's here mostly for convenience and documentation sake
|
5
|
+
class BaseWorkerExtension
|
6
|
+
|
7
|
+
attr_accessor :logger, :process_pool
|
8
|
+
|
9
|
+
# will be called before task gets executed
|
10
|
+
# thowing :stop will halt the task execution process,
|
11
|
+
# no other filters will be executed for this task
|
12
|
+
def before(task)
|
13
|
+
end
|
14
|
+
|
15
|
+
# will be called after task gets executed
|
16
|
+
def after(task, result)
|
17
|
+
end
|
18
|
+
|
19
|
+
# will be called before task gets executed
|
20
|
+
# around is responsible for calling task.run,
|
21
|
+
# failing to do so might result in unpredictable behavior
|
22
|
+
# and failing to run a ProcessPool::EndTask will result in
|
23
|
+
# the process never ending
|
24
|
+
def around(task)
|
25
|
+
end
|
26
|
+
|
27
|
+
# will be called on worker startup, before executing any tasks
|
28
|
+
def startup
|
29
|
+
end
|
30
|
+
|
31
|
+
# will be called on worker shutdown
|
32
|
+
def shutdown
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/init.rb
CHANGED
@@ -4,3 +4,5 @@ require 'json'
|
|
4
4
|
require File.expand_path(File.join(File.dirname(__FILE__), 'simple_logger'))
|
5
5
|
require File.expand_path(File.join(File.dirname(__FILE__), 'simple_queue'))
|
6
6
|
require File.expand_path(File.join(File.dirname(__FILE__), 'process_pool'))
|
7
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'base_worker_extension'))
|
8
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'anonymous_extension'))
|
data/lib/process_pool.rb
CHANGED
@@ -13,14 +13,25 @@ class ProcessPool
|
|
13
13
|
self.workers_count = workers_count
|
14
14
|
self.queue = queue
|
15
15
|
self.worker_pids = []
|
16
|
+
self.extensions = []
|
16
17
|
end
|
17
18
|
|
18
19
|
def schedule(job_class, *args)
|
19
20
|
raise InvalidStateError.new('Can not add more jobs after shut down was called') if is_shutdown?
|
20
|
-
logger.debug("Scheduling task #{job_class}(#{args})")
|
21
|
+
logger.debug("Scheduling task #{job_class}(#{args.collect{ |a| a.inspect }.join(', ')})")
|
21
22
|
push_task(job_class, args)
|
22
23
|
end
|
23
24
|
|
25
|
+
def register_extension(extension)
|
26
|
+
raise InvalidStateError.new('Can not register extensions once the pool is started.') unless is_stopped?
|
27
|
+
raise ArgumentError.new('extension can not be nil') unless extension
|
28
|
+
|
29
|
+
extension.process_pool = self if extension.respond_to?(:process_pool=)
|
30
|
+
extension.logger = logger if extension.respond_to?(:logger=)
|
31
|
+
|
32
|
+
extensions << extension
|
33
|
+
end
|
34
|
+
|
24
35
|
def start
|
25
36
|
raise InvalidStateError.new('Can not start a pool more than once') unless is_stopped?
|
26
37
|
logger.info("Starting process pool")
|
@@ -28,12 +39,16 @@ class ProcessPool
|
|
28
39
|
|
29
40
|
workers_count.times do
|
30
41
|
pid = fork do
|
42
|
+
run_extensions(:startup)
|
43
|
+
at_exit { run_extensions(:shutdown) }
|
31
44
|
child_queue = get_child_queue()
|
32
45
|
while true
|
33
46
|
task_class, args = child_queue.pop
|
34
47
|
begin
|
35
48
|
task = get_task_class(task_class).new(*args)
|
36
|
-
task.
|
49
|
+
run_extensions(:before, task) unless task.is_a?(EndTask)
|
50
|
+
result = task.run
|
51
|
+
run_extensions(:after, task, result)
|
37
52
|
rescue => e
|
38
53
|
logger.warn("Exception occurred while executing task #{task_class}(#{args}): #{e}")
|
39
54
|
end
|
@@ -73,7 +88,7 @@ class ProcessPool
|
|
73
88
|
|
74
89
|
protected
|
75
90
|
|
76
|
-
attr_accessor :state, :logger, :queue, :worker_pids
|
91
|
+
attr_accessor :state, :logger, :queue, :worker_pids, :extensions
|
77
92
|
attr_writer :workers_count
|
78
93
|
|
79
94
|
def push_task(job_class, args)
|
@@ -93,6 +108,14 @@ class ProcessPool
|
|
93
108
|
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
94
109
|
end
|
95
110
|
|
111
|
+
def run_extensions(method, *args)
|
112
|
+
extensions.each do |extension|
|
113
|
+
if extension.respond_to?(method)
|
114
|
+
extension.send(method, *args)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
96
119
|
class EndTask
|
97
120
|
def run
|
98
121
|
exit(0)
|
data/lib/simple_queue.rb
CHANGED
@@ -43,10 +43,14 @@ class SimpleQueue
|
|
43
43
|
|
44
44
|
def self.create
|
45
45
|
file = Tempfile.new('simple_queue')
|
46
|
-
file.
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
path = File.expand_path(file.path)
|
47
|
+
file.close!
|
48
|
+
|
49
|
+
File.open(path, 'w+') do |f|
|
50
|
+
f.puts [].to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
return new(path)
|
50
54
|
end
|
51
55
|
|
52
56
|
def self.get(uri)
|
data/process_pool.gemspec
CHANGED
@@ -5,15 +5,16 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{process_pool}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Adam Pohorecki"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-02-18}
|
13
13
|
s.email = %q{adam@pohorecki.pl}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
16
|
-
"README"
|
16
|
+
"README",
|
17
|
+
"TODO"
|
17
18
|
]
|
18
19
|
s.files = [
|
19
20
|
".gitignore",
|
@@ -21,12 +22,16 @@ Gem::Specification.new do |s|
|
|
21
22
|
"LICENSE",
|
22
23
|
"README",
|
23
24
|
"Rakefile",
|
25
|
+
"TODO",
|
24
26
|
"VERSION",
|
27
|
+
"lib/anonymous_extension.rb",
|
28
|
+
"lib/base_worker_extension.rb",
|
25
29
|
"lib/init.rb",
|
26
30
|
"lib/process_pool.rb",
|
27
31
|
"lib/simple_logger.rb",
|
28
32
|
"lib/simple_queue.rb",
|
29
33
|
"process_pool.gemspec",
|
34
|
+
"test/anonymous_extension_test.rb",
|
30
35
|
"test/process_pool_test.rb",
|
31
36
|
"test/simple_queue_test.rb",
|
32
37
|
"test/test_helper.rb"
|
@@ -37,7 +42,8 @@ Gem::Specification.new do |s|
|
|
37
42
|
s.rubygems_version = %q{1.3.5}
|
38
43
|
s.summary = %q{ProcessPool with interchangeable job queue backends for Ruby}
|
39
44
|
s.test_files = [
|
40
|
-
"test/
|
45
|
+
"test/anonymous_extension_test.rb",
|
46
|
+
"test/process_pool_test.rb",
|
41
47
|
"test/simple_queue_test.rb",
|
42
48
|
"test/test_helper.rb"
|
43
49
|
]
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class AnonymousExtensionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "raise ArgumentError when called with an unsupported method" do
|
6
|
+
assert_raises ArgumentError do
|
7
|
+
AnonymousExtension.new(:unsupported_method) {}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
AnonymousExtension::SUPPORTED_EXTENSION_METHODS.each do |method_name|
|
12
|
+
should "not raise anything when called with #{method_name}" do
|
13
|
+
assert_nothing_raised do
|
14
|
+
AnonymousExtension.new(method_name) {}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with method #{method_name}" do
|
19
|
+
setup do
|
20
|
+
@value = 0
|
21
|
+
@ext = AnonymousExtension.new(method_name) { |x| @value = x }
|
22
|
+
end
|
23
|
+
|
24
|
+
should "execute the block when right method is called" do
|
25
|
+
@ext.send(method_name, 1)
|
26
|
+
assert_equal 1, @value
|
27
|
+
end
|
28
|
+
|
29
|
+
AnonymousExtension::SUPPORTED_EXTENSION_METHODS.each do |other_method|
|
30
|
+
next if method_name == other_method
|
31
|
+
|
32
|
+
should "not execute the block when #{other_method} is called" do
|
33
|
+
@ext.send(other_method, 1)
|
34
|
+
assert_equal 0, @value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/process_pool_test.rb
CHANGED
@@ -65,6 +65,21 @@ class WrongArgumentsTask
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
class WriteToFileTask
|
69
|
+
|
70
|
+
def initialize(path, n)
|
71
|
+
@path = path
|
72
|
+
@n = n
|
73
|
+
end
|
74
|
+
|
75
|
+
def run
|
76
|
+
File.open(@path, 'a+') do |file|
|
77
|
+
file.puts "task #{@n}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
68
83
|
class ProcessPoolTest < Test::Unit::TestCase
|
69
84
|
|
70
85
|
context "state" do
|
@@ -102,6 +117,21 @@ class ProcessPoolTest < Test::Unit::TestCase
|
|
102
117
|
end
|
103
118
|
end
|
104
119
|
|
120
|
+
should "raise InvalidStateError when calling register_extension on a started pool" do
|
121
|
+
@pool.start
|
122
|
+
assert_raises ProcessPool::InvalidStateError do
|
123
|
+
@pool.register_extension(BaseWorkerExtension.new)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
should "raise InvalidStateError when calling register_extension on a shutdown pool" do
|
128
|
+
@pool.start
|
129
|
+
@pool.shutdown
|
130
|
+
assert_raises ProcessPool::InvalidStateError do
|
131
|
+
@pool.register_extension(BaseWorkerExtension.new)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
105
135
|
should "raise InvalidStateError when calling start twice" do
|
106
136
|
@pool.start
|
107
137
|
assert_raises ProcessPool::InvalidStateError do
|
@@ -158,7 +188,7 @@ class ProcessPoolTest < Test::Unit::TestCase
|
|
158
188
|
context :shutdown do
|
159
189
|
setup do
|
160
190
|
@queue = SampleQueue.new
|
161
|
-
@pool = ProcessPool.new(3, @queue, SimpleLogger.new(:debug))
|
191
|
+
@pool = ProcessPool.new(3, @queue, SimpleLogger.new(:debug))
|
162
192
|
@pool.schedule(SampleTask)
|
163
193
|
@pool.stubs(:fork => 1)
|
164
194
|
@pool.start
|
@@ -230,4 +260,185 @@ class ProcessPoolTest < Test::Unit::TestCase
|
|
230
260
|
|
231
261
|
end
|
232
262
|
|
263
|
+
def self.should_write_lines(*lines)
|
264
|
+
should "write lines #{lines.collect{|line| line.inspect}.join(', ')} to file" do
|
265
|
+
text = open(@path).read
|
266
|
+
file_lines = text.split("\n").collect { |line| line.strip }
|
267
|
+
assert_equal lines, file_lines
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def write_to_shared_file(str)
|
272
|
+
File.open(@path, 'a+') do |file|
|
273
|
+
file.puts str
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
context "extensions" do
|
278
|
+
setup do
|
279
|
+
@logger = SimpleLogger.new(:debug)
|
280
|
+
@pool = ProcessPool.new(1, SimpleQueue.create, @logger)
|
281
|
+
@shared_file = Tempfile.new('test')
|
282
|
+
@path = @shared_file.path
|
283
|
+
end
|
284
|
+
|
285
|
+
teardown do
|
286
|
+
@shared_file.close
|
287
|
+
end
|
288
|
+
|
289
|
+
should "raise ArgumentError if called with nil" do
|
290
|
+
assert_raises ArgumentError do
|
291
|
+
@pool.register_extension nil
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
should "inject process_pool to the extension" do
|
296
|
+
extension = BaseWorkerExtension.new
|
297
|
+
assert_nil extension.process_pool
|
298
|
+
@pool.register_extension(extension)
|
299
|
+
assert_equal @pool, extension.process_pool
|
300
|
+
end
|
301
|
+
|
302
|
+
should "inject logger to the extension" do
|
303
|
+
extension = BaseWorkerExtension.new
|
304
|
+
assert_nil extension.logger
|
305
|
+
@pool.register_extension(extension)
|
306
|
+
assert_equal @logger, extension.logger
|
307
|
+
end
|
308
|
+
|
309
|
+
context "with no extensions" do
|
310
|
+
setup do
|
311
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
312
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
313
|
+
|
314
|
+
@pool.start
|
315
|
+
@pool.shutdown
|
316
|
+
end
|
317
|
+
|
318
|
+
should_write_lines "task 1", "task 2"
|
319
|
+
end
|
320
|
+
|
321
|
+
context "with before extension" do
|
322
|
+
setup do
|
323
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
324
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
325
|
+
|
326
|
+
@pool.register_extension AnonymousExtension.new(:before) { |t| write_to_shared_file("before") }
|
327
|
+
|
328
|
+
@pool.start
|
329
|
+
@pool.shutdown
|
330
|
+
end
|
331
|
+
|
332
|
+
should_write_lines "before", "task 1", "before", "task 2"
|
333
|
+
end
|
334
|
+
|
335
|
+
context "with after extension" do
|
336
|
+
setup do
|
337
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
338
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
339
|
+
|
340
|
+
@pool.register_extension AnonymousExtension.new(:after) { |t, r| write_to_shared_file("after") }
|
341
|
+
|
342
|
+
@pool.start
|
343
|
+
@pool.shutdown
|
344
|
+
end
|
345
|
+
|
346
|
+
should_write_lines "task 1", "after", "task 2", "after"
|
347
|
+
end
|
348
|
+
|
349
|
+
context "with around extension" do
|
350
|
+
setup do
|
351
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
352
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
353
|
+
|
354
|
+
@pool.register_extension AnonymousExtension.new(:around) { |t|
|
355
|
+
write_to_shared_file("around 1")
|
356
|
+
t.run
|
357
|
+
write_to_shared_file("around 2")
|
358
|
+
}
|
359
|
+
|
360
|
+
@pool.start
|
361
|
+
@pool.shutdown
|
362
|
+
end
|
363
|
+
|
364
|
+
should_write_lines "around 1", "task 1", "around 2", "around 1", "task 2", "around 2"
|
365
|
+
end
|
366
|
+
|
367
|
+
context "with multiple around extensions" do
|
368
|
+
setup do
|
369
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
370
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
371
|
+
|
372
|
+
@pool.register_extension AnonymousExtension.new(:around) { |t|
|
373
|
+
write_to_shared_file("around a")
|
374
|
+
t.run
|
375
|
+
write_to_shared_file("around b")
|
376
|
+
}
|
377
|
+
|
378
|
+
@pool.register_extension AnonymousExtension.new(:around) { |t|
|
379
|
+
write_to_shared_file("around 1")
|
380
|
+
t.run
|
381
|
+
write_to_shared_file("around 2")
|
382
|
+
}
|
383
|
+
|
384
|
+
@pool.start
|
385
|
+
@pool.shutdown
|
386
|
+
end
|
387
|
+
|
388
|
+
should_write_lines "around a", "around 1", "task 1", "around 2", "around b", "around a", "around 1", "task 2", "around 2", "around b"
|
389
|
+
end
|
390
|
+
|
391
|
+
context "with startup extension" do
|
392
|
+
setup do
|
393
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
394
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
395
|
+
|
396
|
+
@pool.register_extension AnonymousExtension.new(:startup) { write_to_shared_file("startup") }
|
397
|
+
|
398
|
+
@pool.start
|
399
|
+
@pool.shutdown
|
400
|
+
end
|
401
|
+
|
402
|
+
should_write_lines "startup", "task 1", "task 2"
|
403
|
+
end
|
404
|
+
|
405
|
+
context "with shutdown extension" do
|
406
|
+
setup do
|
407
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
408
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
409
|
+
|
410
|
+
@pool.register_extension AnonymousExtension.new(:shutdown) { write_to_shared_file("shutdown") }
|
411
|
+
|
412
|
+
@pool.start
|
413
|
+
@pool.shutdown
|
414
|
+
end
|
415
|
+
|
416
|
+
should_write_lines "task 1", "task 2", "shutdown"
|
417
|
+
end
|
418
|
+
|
419
|
+
context "with all kinds of extensions" do
|
420
|
+
setup do
|
421
|
+
@pool.schedule(WriteToFileTask, @path, 1)
|
422
|
+
@pool.schedule(WriteToFileTask, @path, 2)
|
423
|
+
|
424
|
+
@pool.register_extension AnonymousExtension.new(:around) { |t|
|
425
|
+
write_to_shared_file("around 1")
|
426
|
+
t.run
|
427
|
+
write_to_shared_file("around 2")
|
428
|
+
}
|
429
|
+
|
430
|
+
@pool.register_extension AnonymousExtension.new(:before) { |t| write_to_shared_file("before") }
|
431
|
+
@pool.register_extension AnonymousExtension.new(:after) { |t, r| write_to_shared_file("after") }
|
432
|
+
|
433
|
+
@pool.register_extension AnonymousExtension.new(:startup) { write_to_shared_file("startup") }
|
434
|
+
@pool.register_extension AnonymousExtension.new(:shutdown) { write_to_shared_file("shutdown") }
|
435
|
+
|
436
|
+
@pool.start
|
437
|
+
@pool.shutdown
|
438
|
+
end
|
439
|
+
|
440
|
+
should_write_lines "startup", "before", "around 1", "task 1", "around 2", "after", "before", "around 1", "task 2", "around 2", "after", "shutdown"
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
233
444
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Pohorecki
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-02-18 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -31,18 +31,23 @@ extensions: []
|
|
31
31
|
extra_rdoc_files:
|
32
32
|
- LICENSE
|
33
33
|
- README
|
34
|
+
- TODO
|
34
35
|
files:
|
35
36
|
- .gitignore
|
36
37
|
- Gemfile
|
37
38
|
- LICENSE
|
38
39
|
- README
|
39
40
|
- Rakefile
|
41
|
+
- TODO
|
40
42
|
- VERSION
|
43
|
+
- lib/anonymous_extension.rb
|
44
|
+
- lib/base_worker_extension.rb
|
41
45
|
- lib/init.rb
|
42
46
|
- lib/process_pool.rb
|
43
47
|
- lib/simple_logger.rb
|
44
48
|
- lib/simple_queue.rb
|
45
49
|
- process_pool.gemspec
|
50
|
+
- test/anonymous_extension_test.rb
|
46
51
|
- test/process_pool_test.rb
|
47
52
|
- test/simple_queue_test.rb
|
48
53
|
- test/test_helper.rb
|
@@ -75,6 +80,7 @@ signing_key:
|
|
75
80
|
specification_version: 3
|
76
81
|
summary: ProcessPool with interchangeable job queue backends for Ruby
|
77
82
|
test_files:
|
83
|
+
- test/anonymous_extension_test.rb
|
78
84
|
- test/process_pool_test.rb
|
79
85
|
- test/simple_queue_test.rb
|
80
86
|
- test/test_helper.rb
|