parallizer 0.0.4 → 0.1.0
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/README.md +45 -29
- data/VERSION +1 -1
- data/lib/parallizer.rb +38 -34
- data/lib/parallizer/proxy.rb +21 -10
- data/parallizer.gemspec +4 -4
- data/test/{test_helper.rb → helper.rb} +0 -0
- data/test/parallizer/method_call_notifier_test.rb +1 -1
- data/test/parallizer/proxy_test.rb +55 -24
- data/test/parallizer_test.rb +24 -28
- metadata +4 -4
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Parallizer - Execute your service layer in parallel
|
2
2
|
|
3
|
-
Parallizer executes service methods in parallel, stores the method results,
|
3
|
+
Parallizer executes service methods in parallel, stores the method results, and creates a proxy of your service with those results. Your application then uses the short-lived service proxy (think of a single request for a web application) and calls your methods without again executing the underlying implementation. For applications that make considerable use of web service calls, Parallizer can give you a considerable performance boost.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -13,51 +13,60 @@ Parallizer executes service methods in parallel, stores the method results, then
|
|
13
13
|
Here's an example service.
|
14
14
|
|
15
15
|
```ruby
|
16
|
+
require 'rubygems'
|
16
17
|
require 'net/http'
|
18
|
+
require 'nokogiri'
|
17
19
|
|
18
20
|
class SearchService
|
19
|
-
def
|
20
|
-
Net::HTTP.get('www.google.com', '
|
21
|
+
def top_urls_for_foo
|
22
|
+
parse_search_result_for_urls(Net::HTTP.get('www.google.com', '/search?q=foo'))
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
24
|
-
Net::HTTP.get('www.google.com', '
|
25
|
+
def top_urls_for_bar
|
26
|
+
parse_search_result_for_urls(Net::HTTP.get('www.google.com', '/search?q=bar'))
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_search_result_for_urls(content)
|
32
|
+
Nokogiri::HTML.parse(content).search('h3.r > a').collect(&:attributes).collect{ |attrs| attrs['href'].value }
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
28
36
|
$search_service = SearchService.new
|
29
37
|
```
|
30
38
|
|
31
|
-
Now create a Parallizer for that service and add all of the methods you intend to call.
|
39
|
+
Now create a Parallizer for that service and add all of the methods you intend to call. This begins the execution of the service methods in worker threads. Then create a service proxy that uses the stored results of the method calls.
|
32
40
|
|
33
41
|
```ruby
|
34
42
|
require 'parallizer'
|
35
43
|
|
36
44
|
parallizer = Parallizer.new($search_service)
|
37
|
-
parallizer.add.
|
38
|
-
parallizer.add.
|
39
|
-
search_service = parallizer.
|
45
|
+
parallizer.add.top_urls_for_foo
|
46
|
+
parallizer.add.top_urls_for_bar
|
47
|
+
search_service = parallizer.create_proxy
|
40
48
|
```
|
41
49
|
|
42
|
-
Now use that service proxy in your application logic.
|
50
|
+
Now use that service proxy in your application logic. Calls to these methods will not make an HTTP request
|
51
|
+
and will not parse HTML. That was done by the parallel worker threads.
|
43
52
|
|
44
53
|
```ruby
|
45
|
-
puts search_service.
|
46
|
-
puts search_service.
|
54
|
+
puts search_service.top_urls_for_foo
|
55
|
+
puts search_service.top_urls_for_bar
|
47
56
|
```
|
48
57
|
|
49
58
|
Additional calls in your application logic will not result in an additional call to the underlying service.
|
50
59
|
|
51
60
|
```ruby
|
52
61
|
# Called twice, but no extra service call. (Be careful not to mutate the returned object!)
|
53
|
-
puts search_service.
|
54
|
-
puts search_service.
|
62
|
+
puts search_service.top_urls_for_foo
|
63
|
+
puts search_service.top_urls_for_foo
|
55
64
|
```
|
56
65
|
|
57
66
|
If there are additional methods on your service that were not parallized, you can still call them.
|
58
67
|
|
59
68
|
```ruby
|
60
|
-
puts search_service.
|
69
|
+
puts search_service.top_urls_for_foobar # makes an HTTP request and parses result
|
61
70
|
```
|
62
71
|
|
63
72
|
### Parallizing methods with parameters
|
@@ -66,11 +75,18 @@ Parallizing also works on service methods with parameters.
|
|
66
75
|
|
67
76
|
```ruby
|
68
77
|
require 'net/http'
|
78
|
+
require 'nokogiri'
|
69
79
|
require 'cgi'
|
70
80
|
|
71
81
|
class SearchService
|
72
|
-
def
|
73
|
-
Net::HTTP.get('www.google.com', "
|
82
|
+
def top_urls(search_term)
|
83
|
+
parse_search_result_for_urls(Net::HTTP.get('www.google.com', "/search?q=#{CGI.escape(search_term)}"))
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def parse_search_result_for_urls(content)
|
89
|
+
Nokogiri::HTML.parse(content).search('h3.r > a').collect(&:attributes).collect{ |attrs| attrs['href'].value }
|
74
90
|
end
|
75
91
|
end
|
76
92
|
|
@@ -83,17 +99,17 @@ The parallel execution and proxy creation.
|
|
83
99
|
require 'parallizer'
|
84
100
|
|
85
101
|
parallizer = Parallizer.new($search_service)
|
86
|
-
parallizer.add.
|
87
|
-
parallizer.add.
|
88
|
-
search_service = parallizer.
|
102
|
+
parallizer.add.top_urls('foo')
|
103
|
+
parallizer.add.top_urls('bar')
|
104
|
+
search_service = parallizer.create_proxy
|
89
105
|
```
|
90
106
|
|
91
107
|
Using the service proxy in your application logic.
|
92
108
|
|
93
109
|
```ruby
|
94
|
-
puts search_service.
|
95
|
-
puts search_service.
|
96
|
-
puts search_service.
|
110
|
+
puts search_service.top_urls('foo') # returns stored value
|
111
|
+
puts search_service.top_urls('bar') # returns stored value
|
112
|
+
puts search_service.top_urls('foobar') # makes an HTTP request and parses result
|
97
113
|
```
|
98
114
|
|
99
115
|
|
@@ -108,24 +124,24 @@ require 'parallizer'
|
|
108
124
|
parallizer = Parallizer.new(Net::HTTP)
|
109
125
|
parallizer.add.get('www.google.com', '/?q=foo')
|
110
126
|
parallizer.add.get('www.google.com', '/?q=bar')
|
111
|
-
http_service = parallizer.
|
127
|
+
http_service = parallizer.create_proxy
|
112
128
|
```
|
113
129
|
|
114
130
|
Use the service proxy.
|
115
131
|
|
116
132
|
```ruby
|
117
133
|
# use your service proxy
|
118
|
-
http_service.get('www.google.com', '
|
119
|
-
http_service.get('www.google.com', '
|
120
|
-
http_service.get('www.google.com', '
|
134
|
+
http_service.get('www.google.com', '/search?q=foo') # returns stored value
|
135
|
+
http_service.get('www.google.com', '/search?q=bar') # returns stored value
|
136
|
+
http_service.get('www.google.com', '/search?q=foobar') # makes an HTTP request and parses result
|
121
137
|
```
|
122
138
|
|
123
139
|
|
124
140
|
# Credits
|
125
141
|
|
126
|
-
[Parallizer](https://github.com/michaelgpearce/parallizer) is maintained by [Michael Pearce](http://github.com/michaelgpearce) and is funded by [
|
142
|
+
[Parallizer](https://github.com/michaelgpearce/parallizer) is maintained by [Michael Pearce](http://github.com/michaelgpearce) and is funded by [Rafter](http://www.rafter.com "Rafter").
|
127
143
|
|
128
|
-

|
129
145
|
|
130
146
|
# Copyright
|
131
147
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/lib/parallizer.rb
CHANGED
@@ -1,56 +1,60 @@
|
|
1
|
-
require 'set'
|
2
1
|
require 'work_queue'
|
3
2
|
require 'parallizer/proxy'
|
4
3
|
require 'parallizer/method_call_notifier'
|
5
4
|
|
6
5
|
class Parallizer
|
7
|
-
|
6
|
+
attr_reader :calls, :call_infos, :client, :proxy
|
8
7
|
|
9
8
|
def initialize(client)
|
10
|
-
|
11
|
-
|
9
|
+
@client = client
|
10
|
+
@call_infos = {}
|
12
11
|
end
|
13
12
|
|
14
13
|
def add
|
15
14
|
MethodCallNotifier.new do |*args|
|
16
|
-
|
15
|
+
add_call(*args)
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
|
-
def
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def execute
|
25
|
-
Parallizer.execute_all(self).first
|
19
|
+
def calls
|
20
|
+
@call_infos.keys
|
26
21
|
end
|
27
22
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
23
|
+
def add_call(method_name, *args)
|
24
|
+
raise ArgumentError, "Cannot add calls after proxy has been generated" if @proxy
|
25
|
+
|
26
|
+
method_name_and_args = [method_name.to_sym, *args]
|
27
|
+
|
28
|
+
call_info = {
|
29
|
+
:complete? => false,
|
30
|
+
:result => nil,
|
31
|
+
:exception => nil,
|
32
|
+
:condition_variable => ConditionVariable.new,
|
33
|
+
:mutex => Mutex.new
|
34
|
+
}
|
35
|
+
call_infos[method_name_and_args] = call_info
|
36
|
+
|
37
|
+
Parallizer.work_queue.enqueue_b do
|
38
|
+
call_info[:mutex].synchronize do
|
39
|
+
begin
|
40
|
+
call_info[:result] = client.send(*method_name_and_args)
|
41
|
+
rescue Exception => e
|
42
|
+
call_info[:exception] = e
|
43
|
+
ensure
|
44
|
+
call_info[:complete?] = true
|
45
|
+
call_info[:condition_variable].signal
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_proxy
|
52
|
+
raise ArgumentError, "Cannot create another proxy" if @proxy
|
49
53
|
|
50
|
-
Parallizer.
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
Parallizer::Proxy.new(client, call_infos)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.work_queue
|
58
|
+
@parallizer_work_queue ||= WorkQueue.new(10)
|
55
59
|
end
|
56
60
|
end
|
data/lib/parallizer/proxy.rb
CHANGED
@@ -1,27 +1,38 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'set'
|
2
3
|
|
3
4
|
class Parallizer
|
4
5
|
class Proxy
|
5
|
-
def initialize(client,
|
6
|
+
def initialize(client, call_infos)
|
6
7
|
@client = client
|
7
|
-
@
|
8
|
+
@call_infos = call_infos
|
8
9
|
end
|
9
10
|
|
10
11
|
def method_missing(name, *args, &block)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
value = nil
|
13
|
+
|
14
|
+
if call_info = @call_infos[[name, *args]]
|
15
|
+
call_info[:mutex].synchronize do
|
16
|
+
if !call_info[:complete?]
|
17
|
+
# not done, so lets wait for signal of completion
|
18
|
+
call_info[:condition_variable].wait(call_info[:mutex])
|
19
|
+
end
|
20
|
+
# we now have our result from the worker thread
|
21
|
+
|
22
|
+
raise call_info[:exception] if call_info[:exception]
|
23
|
+
|
24
|
+
value = call_info[:result]
|
17
25
|
end
|
18
26
|
else
|
19
|
-
|
27
|
+
# pass through to client since not added
|
28
|
+
value = @client.send(*[name, *args], &block)
|
20
29
|
end
|
30
|
+
|
31
|
+
value
|
21
32
|
end
|
22
33
|
|
23
34
|
def respond_to?(name, include_private = false, &block)
|
24
|
-
@execution_methods ||= Set.new(@
|
35
|
+
@execution_methods ||= Set.new(@call_infos.keys.collect(&:first))
|
25
36
|
|
26
37
|
if @execution_methods.include?(name.to_sym)
|
27
38
|
true
|
data/parallizer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "parallizer"
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Pearce"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-08-04"
|
13
13
|
s.description = "Execute your service layer in parallel."
|
14
14
|
s.email = "michael.pearce@bookrenter.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,10 +27,10 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/parallizer/method_call_notifier.rb",
|
28
28
|
"lib/parallizer/proxy.rb",
|
29
29
|
"parallizer.gemspec",
|
30
|
+
"test/helper.rb",
|
30
31
|
"test/parallizer/method_call_notifier_test.rb",
|
31
32
|
"test/parallizer/proxy_test.rb",
|
32
|
-
"test/parallizer_test.rb"
|
33
|
-
"test/test_helper.rb"
|
33
|
+
"test/parallizer_test.rb"
|
34
34
|
]
|
35
35
|
s.homepage = "http://github.com/michaelgpearce/parallizer"
|
36
36
|
s.licenses = ["MIT"]
|
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
class Parallizer::ProxyTest < Test::Unit::TestCase
|
4
4
|
DEFAULT_RETURN_VALUE = "return value"
|
@@ -12,53 +12,82 @@ class Parallizer::ProxyTest < Test::Unit::TestCase
|
|
12
12
|
context ".method_missing" do
|
13
13
|
setup do
|
14
14
|
@client = TestObject.new
|
15
|
+
@call_key = []
|
16
|
+
@call_info = {:result => nil, :exception => nil, :complete? => true,
|
17
|
+
:condition_variable => ConditionVariable.new, :mutex => Mutex.new }
|
18
|
+
end
|
19
|
+
|
20
|
+
execute do
|
21
|
+
call_infos = { @call_key => @call_info }
|
22
|
+
proxy = Parallizer::Proxy.new(@client, call_infos)
|
23
|
+
proxy.send(*@call_key) rescue $!
|
15
24
|
end
|
16
25
|
|
17
26
|
context "with method that exists on client" do
|
18
|
-
context "with method and arg
|
27
|
+
context "with method and arg call info" do
|
19
28
|
setup do
|
20
|
-
@
|
21
|
-
@method_arg = "some arg"
|
22
|
-
@execution_results = {[:a_method, @method_arg] => {:result => @method_result}}
|
29
|
+
@call_key += [:a_method, "some value"]
|
23
30
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
31
|
+
|
32
|
+
context "with not complete?" do
|
33
|
+
setup do
|
34
|
+
@call_info[:complete?] = false
|
35
|
+
@call_info[:condition_variable].expects(:wait).with(@call_info[:mutex])
|
36
|
+
@call_info[:result] = 'this is a value'
|
37
|
+
end
|
38
|
+
|
39
|
+
should do
|
40
|
+
assert_equal @call_info[:result], @execute_result
|
41
|
+
end
|
27
42
|
end
|
28
|
-
|
29
|
-
context "with
|
43
|
+
|
44
|
+
context "with complete? call info" do
|
30
45
|
setup do
|
31
|
-
@
|
46
|
+
@call_info[:complete?] = true
|
32
47
|
end
|
33
48
|
|
34
|
-
|
35
|
-
|
36
|
-
|
49
|
+
context "with an exception" do
|
50
|
+
setup do
|
51
|
+
@call_info[:exception] = StandardError.new('An Exception')
|
52
|
+
end
|
53
|
+
|
54
|
+
should "raise exception" do
|
55
|
+
assert_equal @call_info[:exception], @execute_result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with a result" do
|
60
|
+
setup do
|
61
|
+
@call_info[:result] = "a result"
|
62
|
+
end
|
63
|
+
|
64
|
+
should "return result" do
|
65
|
+
assert_equal @call_info[:result], @execute_result
|
37
66
|
end
|
38
67
|
end
|
39
68
|
end
|
40
69
|
end
|
41
70
|
|
42
|
-
context "with method and arg not in execute result" do
|
71
|
+
context "with no method and arg not in execute result" do
|
43
72
|
setup do
|
44
|
-
@
|
73
|
+
@call_key += [:a_method, "some parameter"]
|
74
|
+
@call_info = nil
|
45
75
|
end
|
46
|
-
|
76
|
+
|
47
77
|
should "return value from client object" do
|
48
|
-
assert_equal DEFAULT_RETURN_VALUE,
|
78
|
+
assert_equal DEFAULT_RETURN_VALUE, @execute_result
|
49
79
|
end
|
50
80
|
end
|
51
81
|
end
|
52
82
|
|
53
83
|
context "with method that does not exist on client" do
|
54
84
|
setup do
|
55
|
-
@
|
85
|
+
@call_key += [:unknown_method, "some parameter"]
|
86
|
+
@call_info = nil
|
56
87
|
end
|
57
88
|
|
58
89
|
should "raise exception" do
|
59
|
-
|
60
|
-
Parallizer::Proxy.new(@client, @execution_results).unknown_method()
|
61
|
-
end
|
90
|
+
assert_equal NoMethodError, @execute_result.class
|
62
91
|
end
|
63
92
|
end
|
64
93
|
end
|
@@ -66,8 +95,10 @@ class Parallizer::ProxyTest < Test::Unit::TestCase
|
|
66
95
|
context ".respond_to?" do
|
67
96
|
setup do
|
68
97
|
client = TestObject.new
|
69
|
-
|
70
|
-
|
98
|
+
call_key = [:a_method, 'valid argument']
|
99
|
+
call_info = {:result => nil, :exception => nil, :complete? => true,
|
100
|
+
:condition_variable => ConditionVariable.new, :mutex => Mutex.new }
|
101
|
+
@proxy = Parallizer::Proxy.new(client, { call_key => call_info })
|
71
102
|
end
|
72
103
|
|
73
104
|
should "respond to proxy method as symbol" do
|
data/test/parallizer_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
class ParallizerTest < Test::Unit::TestCase
|
4
4
|
class TestObject
|
@@ -43,7 +43,17 @@ class ParallizerTest < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
execute do
|
46
|
-
@parallizer.add_call(@method, 'arg')
|
46
|
+
@parallizer.add_call(@method, 'arg') rescue $!
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with proxy already created" do
|
50
|
+
setup do
|
51
|
+
@parallizer.instance_variable_set(:@proxy, mock('proxy'))
|
52
|
+
end
|
53
|
+
|
54
|
+
should "raise ArgumentError" do
|
55
|
+
assert_equal ArgumentError, @execute_result.class
|
56
|
+
end
|
47
57
|
end
|
48
58
|
|
49
59
|
context "with string method name added" do
|
@@ -67,14 +77,14 @@ class ParallizerTest < Test::Unit::TestCase
|
|
67
77
|
end
|
68
78
|
end
|
69
79
|
|
70
|
-
context ".
|
80
|
+
context ".create_proxy" do
|
71
81
|
setup do
|
72
82
|
@client = TestObject.new
|
73
83
|
@parallizer = Parallizer.new(@client)
|
74
84
|
end
|
75
85
|
|
76
86
|
execute do
|
77
|
-
@proxy = @parallizer.
|
87
|
+
@proxy = @parallizer.create_proxy rescue $!
|
78
88
|
end
|
79
89
|
|
80
90
|
context "with existing method on client" do
|
@@ -90,30 +100,16 @@ class ParallizerTest < Test::Unit::TestCase
|
|
90
100
|
assert_equal Thread.current, @proxy.another_method
|
91
101
|
end
|
92
102
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@parallizer2.add_call(:a_method)
|
103
|
-
end
|
104
|
-
|
105
|
-
execute do
|
106
|
-
@proxy1, @proxy2 = Parallizer.execute_all(@parallizer1, @parallizer2)
|
107
|
-
end
|
108
|
-
|
109
|
-
should "execute methods with add_call in a separate thread" do
|
110
|
-
assert_not_equal Thread.current, @proxy1.a_method('arg')
|
111
|
-
assert_not_equal Thread.current, @proxy2.a_method
|
112
|
-
end
|
113
|
-
|
114
|
-
should "execute methods not added with add_call in current thread" do
|
115
|
-
assert_equal Thread.current, @proxy1.another_method
|
116
|
-
assert_equal Thread.current, @proxy2.another_method
|
103
|
+
|
104
|
+
context "with proxy already created" do
|
105
|
+
setup do
|
106
|
+
@parallizer.instance_variable_set(:@proxy, mock('proxy'))
|
107
|
+
end
|
108
|
+
|
109
|
+
should "raise ArgumentError" do
|
110
|
+
assert_equal ArgumentError, @execute_result.class
|
111
|
+
end
|
117
112
|
end
|
113
|
+
|
118
114
|
end
|
119
115
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
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: 2012-
|
12
|
+
date: 2012-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -109,10 +109,10 @@ files:
|
|
109
109
|
- lib/parallizer/method_call_notifier.rb
|
110
110
|
- lib/parallizer/proxy.rb
|
111
111
|
- parallizer.gemspec
|
112
|
+
- test/helper.rb
|
112
113
|
- test/parallizer/method_call_notifier_test.rb
|
113
114
|
- test/parallizer/proxy_test.rb
|
114
115
|
- test/parallizer_test.rb
|
115
|
-
- test/test_helper.rb
|
116
116
|
homepage: http://github.com/michaelgpearce/parallizer
|
117
117
|
licenses:
|
118
118
|
- MIT
|
@@ -128,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
128
|
version: '0'
|
129
129
|
segments:
|
130
130
|
- 0
|
131
|
-
hash: -
|
131
|
+
hash: -894887093549594031
|
132
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
133
|
none: false
|
134
134
|
requirements:
|