parallizer 0.1.0 → 0.2.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 +16 -0
- data/VERSION +1 -1
- data/lib/parallizer.rb +29 -15
- data/lib/parallizer/proxy.rb +6 -1
- data/parallizer.gemspec +2 -2
- data/test/parallizer/proxy_test.rb +17 -1
- data/test/parallizer_test.rb +37 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -137,6 +137,22 @@ http_service.get('www.google.com', '/search?q=foobar') # makes an HTTP request a
|
|
137
137
|
```
|
138
138
|
|
139
139
|
|
140
|
+
### Service Method Retries
|
141
|
+
|
142
|
+
Parallize also allows you to retry methods that fail (any exception raised is considered a failure).
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
require 'net/http'
|
146
|
+
require 'parallizer'
|
147
|
+
|
148
|
+
parallizer = Parallizer.new(Net::HTTP, :retries => 3)
|
149
|
+
parallizer.add.get('www.google.com', '/?q=foo')
|
150
|
+
http_service = parallizer.create_proxy
|
151
|
+
|
152
|
+
http_service.get('www.google.com', '/?q=foo') # Will be called up to 4 times
|
153
|
+
```
|
154
|
+
|
155
|
+
|
140
156
|
# Credits
|
141
157
|
|
142
158
|
[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").
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/parallizer.rb
CHANGED
@@ -3,10 +3,11 @@ require 'parallizer/proxy'
|
|
3
3
|
require 'parallizer/method_call_notifier'
|
4
4
|
|
5
5
|
class Parallizer
|
6
|
-
attr_reader :calls, :call_infos, :client, :proxy
|
6
|
+
attr_reader :calls, :call_infos, :client, :proxy, :options
|
7
7
|
|
8
|
-
def initialize(client)
|
8
|
+
def initialize(client, options = {})
|
9
9
|
@client = client
|
10
|
+
@options = {:retries => 0}.merge(options)
|
10
11
|
@call_infos = {}
|
11
12
|
end
|
12
13
|
|
@@ -30,22 +31,12 @@ class Parallizer
|
|
30
31
|
:result => nil,
|
31
32
|
:exception => nil,
|
32
33
|
:condition_variable => ConditionVariable.new,
|
33
|
-
:mutex => Mutex.new
|
34
|
+
:mutex => Mutex.new,
|
35
|
+
:retries => options[:retries]
|
34
36
|
}
|
35
37
|
call_infos[method_name_and_args] = call_info
|
36
38
|
|
37
|
-
|
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
|
-
end
|
47
|
-
end
|
48
|
-
end
|
39
|
+
enqueue_call_info(call_info, method_name_and_args)
|
49
40
|
end
|
50
41
|
|
51
42
|
def create_proxy
|
@@ -57,4 +48,27 @@ class Parallizer
|
|
57
48
|
def self.work_queue
|
58
49
|
@parallizer_work_queue ||= WorkQueue.new(10)
|
59
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def enqueue_call_info(call_info, method_name_and_args)
|
55
|
+
Parallizer.work_queue.enqueue_b do
|
56
|
+
call_info[:mutex].synchronize do
|
57
|
+
begin
|
58
|
+
(call_info[:retries] + 1).times do
|
59
|
+
begin
|
60
|
+
call_info[:exception] = nil # reset exception before each send attempt
|
61
|
+
call_info[:result] = client.send(*method_name_and_args)
|
62
|
+
break # success
|
63
|
+
rescue Exception => e
|
64
|
+
call_info[:exception] = e
|
65
|
+
end
|
66
|
+
end
|
67
|
+
ensure
|
68
|
+
call_info[:complete?] = true
|
69
|
+
call_info[:condition_variable].signal
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
60
74
|
end
|
data/lib/parallizer/proxy.rb
CHANGED
@@ -19,7 +19,12 @@ class Parallizer
|
|
19
19
|
end
|
20
20
|
# we now have our result from the worker thread
|
21
21
|
|
22
|
-
|
22
|
+
if call_info[:exception]
|
23
|
+
# add the current call stack to the exception backtrace
|
24
|
+
exception = call_info[:exception].clone
|
25
|
+
exception.set_backtrace((call_info[:exception].backtrace || []) + caller)
|
26
|
+
raise exception
|
27
|
+
end
|
23
28
|
|
24
29
|
value = call_info[:result]
|
25
30
|
end
|
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.
|
8
|
+
s.version = "0.2.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-08-
|
12
|
+
s.date = "2012-08-15"
|
13
13
|
s.description = "Execute your service layer in parallel."
|
14
14
|
s.email = "michael.pearce@bookrenter.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -49,10 +49,26 @@ class Parallizer::ProxyTest < Test::Unit::TestCase
|
|
49
49
|
context "with an exception" do
|
50
50
|
setup do
|
51
51
|
@call_info[:exception] = StandardError.new('An Exception')
|
52
|
+
@call_info[:exception].set_backtrace(["/tmp/foo.rb:123:in `in a_worker_thread_method'"])
|
52
53
|
end
|
53
54
|
|
55
|
+
execute do
|
56
|
+
def a_calling_thread_method
|
57
|
+
call_infos = { @call_key => @call_info }
|
58
|
+
proxy = Parallizer::Proxy.new(@client, call_infos)
|
59
|
+
proxy.send(*@call_key) rescue $!
|
60
|
+
end
|
61
|
+
a_calling_thread_method
|
62
|
+
end
|
63
|
+
|
54
64
|
should "raise exception" do
|
55
|
-
assert_equal @call_info[:exception], @execute_result
|
65
|
+
assert_equal @call_info[:exception].class, @execute_result.class
|
66
|
+
assert_equal @call_info[:exception].message, @execute_result.message
|
67
|
+
end
|
68
|
+
|
69
|
+
should "append backtrace of current call" do
|
70
|
+
assert @execute_result.backtrace.grep /a_worker_thread_method/
|
71
|
+
assert @execute_result.backtrace.grep /a_calling_thread_method/
|
56
72
|
end
|
57
73
|
end
|
58
74
|
|
data/test/parallizer_test.rb
CHANGED
@@ -110,6 +110,43 @@ class ParallizerTest < Test::Unit::TestCase
|
|
110
110
|
assert_equal ArgumentError, @execute_result.class
|
111
111
|
end
|
112
112
|
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "with retries" do
|
116
|
+
setup do
|
117
|
+
@retries = 3
|
118
|
+
@client = stub('a client')
|
119
|
+
@method = :a_sometimes_failing_method
|
120
|
+
end
|
121
|
+
|
122
|
+
execute do
|
123
|
+
parallizer = Parallizer.new(@client, :retries => @retries)
|
124
|
+
parallizer.add_call(@method)
|
125
|
+
proxy = parallizer.create_proxy
|
126
|
+
proxy.send(@method) rescue $!
|
127
|
+
end
|
113
128
|
|
129
|
+
context "with success on last retry" do
|
130
|
+
setup do
|
131
|
+
# NOTE: added reverse order
|
132
|
+
@client.expects(@method).returns('success')
|
133
|
+
@retries.times { @client.expects(@method).raises('an error') }
|
134
|
+
end
|
135
|
+
|
136
|
+
should "return successful method response" do
|
137
|
+
assert_equal 'success', @execute_result
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
context "with failures greater than retries" do
|
143
|
+
setup do
|
144
|
+
(@retries + 1).times { @client.expects(@method).raises('an error') }
|
145
|
+
end
|
146
|
+
|
147
|
+
should "return successful method response" do
|
148
|
+
assert_equal 'an error', @execute_result.message
|
149
|
+
end
|
150
|
+
end
|
114
151
|
end
|
115
152
|
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.
|
4
|
+
version: 0.2.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-08-
|
12
|
+
date: 2012-08-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -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: 1438464558148381221
|
132
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
133
|
none: false
|
134
134
|
requirements:
|