parallizer 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
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
- 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
- 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
@@ -19,7 +19,12 @@ class Parallizer
19
19
  end
20
20
  # we now have our result from the worker thread
21
21
 
22
- raise call_info[:exception] if call_info[:exception]
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.1.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-04"
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
 
@@ -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.1.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-04 00:00:00.000000000 Z
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: -894887093549594031
131
+ hash: 1438464558148381221
132
132
  required_rubygems_version: !ruby/object:Gem::Requirement
133
133
  none: false
134
134
  requirements: