process_pool 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|