pebbles-river 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0738174b6c9733edbe9524576e2ecf48ca2ad56e
4
- data.tar.gz: bdf513a26a16bd44be5a02dec8af1ac9b11f467f
3
+ metadata.gz: 32827f1f43724f8f2d5cf53943d89b519be5be11
4
+ data.tar.gz: 38db2f8b16ea69ca288e4f5c26c5debe1556356a
5
5
  SHA512:
6
- metadata.gz: 9068b048fa0c91a0640d15d77756dc742c3add7aa0a3106fd50178bf86e58717caa0d917497879b92394b596d74353ae8ca7a9b2ee3ceda8a68455e0d4a6689b
7
- data.tar.gz: 8f0747a995edcd03ca44e64122ef63187904263fe248a22417860a44f854da54ad40c4da1629a448868d0fca7f30ca1595648c64d70a1bb8788f488672fbef19
6
+ metadata.gz: 077a5f0d4d2dc0f2f02cd38b839b49bd14a5bb2201023e2fbdc3fc4f6e4ee6f2370fceba64d97e10e17fb609f14bb8f4af1601acbe8c439b3b23ebef4900b237
7
+ data.tar.gz: b2b43a50bdeba51c83dcdebec4bf94dce4096d239aabd7189954a19d6446c775949ca92eb0b78ca61453c4aab249676da214d425f8bc3d508c5eb01bca269a33
@@ -0,0 +1,17 @@
1
+ module Pebbles
2
+ module River
3
+
4
+ class ConnectionError < StandardError
5
+ attr_reader :connection_exception
6
+
7
+ def initialize(message, connection_exception = nil)
8
+ super(message)
9
+ @connection_exception = connection_exception
10
+ end
11
+ end
12
+
13
+ class ConnectFailure < ConnectionError; end
14
+ class SendFailure < ConnectionError; end
15
+
16
+ end
17
+ end
@@ -1,17 +1,6 @@
1
1
  module Pebbles
2
2
  module River
3
3
 
4
- class SendFailure < StandardError
5
-
6
- attr_reader :connection_exception
7
-
8
- def initialize(message, connection_exception = nil)
9
- super(message)
10
- @connection_exception = connection_exception
11
- end
12
-
13
- end
14
-
15
4
  class River
16
5
 
17
6
  attr_reader :environment
@@ -20,6 +9,7 @@ module Pebbles
20
9
  options = {environment: options} if options.is_a?(String) # Backwards compatibility
21
10
 
22
11
  @environment = (options[:environment] || ENV['RACK_ENV'] || 'development').dup.freeze
12
+ @last_connect_attempt = nil
23
13
  end
24
14
 
25
15
  def connected?
@@ -28,18 +18,26 @@ module Pebbles
28
18
 
29
19
  def connect
30
20
  unless connected?
31
- bunny.start
32
- bunny.qos
21
+ handle_connection_error do
22
+ bunny.start
23
+ bunny.qos
24
+ end
33
25
  end
34
26
  end
35
27
 
36
28
  def disconnect
37
- bunny.stop if connected?
29
+ if connected?
30
+ begin
31
+ bunny.stop
32
+ rescue *CONNECTION_EXCEPTIONS
33
+ # Ignore
34
+ end
35
+ end
38
36
  end
39
37
 
40
38
  def publish(options = {})
41
39
  connect
42
- handle_connection_error do
40
+ handle_connection_error(SendFailure) do
43
41
  exchange.publish(options.to_json,
44
42
  persistent: options.fetch(:persistent, true),
45
43
  key: Routing.routing_key_for(options.slice(:event, :uid)))
@@ -79,21 +77,32 @@ module Pebbles
79
77
  @exchange ||= bunny.exchange(exchange_name, EXCHANGE_OPTIONS.dup)
80
78
  end
81
79
 
82
- def handle_connection_error(&block)
83
- retry_until = nil
84
- begin
85
- yield
86
- rescue *CONNECTION_EXCEPTIONS => exception
87
- retry_until ||= Time.now + 4
88
- if Time.now < retry_until
89
- sleep(0.5)
80
+ def handle_connection_error(exception_klass = ConnectFailure, &block)
81
+ last_exception = nil
82
+ Timeout.timeout(MAX_RETRY_TIMEOUT) do
83
+ retry_until, retry_count = nil, 0
84
+ begin
85
+ yield
86
+ rescue *CONNECTION_EXCEPTIONS => exception
87
+ last_exception = exception
88
+ retry_count += 1
89
+ backoff(retry_count)
90
90
  retry
91
- else
92
- raise SendFailure.new(exception.message, exception)
93
91
  end
94
92
  end
93
+ rescue Timeout::Error => timeout
94
+ last_exception ||= timeout
95
+ raise exception_klass.new(last_exception.message, last_exception)
95
96
  end
96
97
 
98
+ def backoff(iteration)
99
+ sleep([(1.0 / 2.0 * (2.0 ** [30, iteration].min - 1.0)).ceil, MAX_BACKOFF_SECONDS].min)
100
+ end
101
+
102
+ MAX_RETRY_TIMEOUT = 10
103
+
104
+ MAX_BACKOFF_SECONDS = MAX_RETRY_TIMEOUT
105
+
97
106
  QUEUE_OPTIONS = {durable: true}.freeze
98
107
 
99
108
  EXCHANGE_OPTIONS = {type: :topic, durable: :true}.freeze
@@ -1,5 +1,5 @@
1
1
  module Pebbles
2
2
  module River
3
- VERSION = "0.0.1"
3
+ VERSION = '0.0.2'
4
4
  end
5
5
  end
data/lib/pebbles/river.rb CHANGED
@@ -6,6 +6,7 @@ require 'pebblebed/uid'
6
6
  require 'servolux'
7
7
 
8
8
  require_relative "river/version"
9
+ require_relative "river/errors"
9
10
  require_relative "river/message"
10
11
  require_relative "river/worker"
11
12
  require_relative "river/subscription"
@@ -114,6 +114,10 @@ describe Pebbles::River::River do
114
114
 
115
115
  subject.stub(:exchange) { exchange }
116
116
  subject.stub(:sleep) { }
117
+ Timeout.stub(:timeout) { |&block|
118
+ block.call
119
+ }
120
+ expect(Timeout).to receive(:timeout).at_least(1).times
117
121
 
118
122
  expect(subject).to receive(:sleep).at_least(2).times
119
123
 
@@ -126,17 +130,33 @@ describe Pebbles::River::River do
126
130
 
127
131
  CONNECTION_EXCEPTIONS.each do |exception_class|
128
132
  context "on permanent failure with #{exception_class}" do
129
- it "re-raises #{exception_class} wrapped in SendFailure exception" do
133
+ it "retries with exponential backoff until timeout and gives up with SendFailure" do
130
134
  exchange = double('exchange')
131
135
  exchange.stub(:publish) do
132
136
  raise exception_class.new
133
137
  end
134
-
135
138
  subject.stub(:exchange) { exchange }
136
- subject.stub(:sleep) { }
137
139
 
138
- expect(-> { subject.publish({event: 'explode', uid: 'thing:rspec$1'})}).to raise_error(
139
- Pebbles::River::SendFailure)
140
+ count, sleeps = 0, []
141
+ subject.stub(:sleep) { |t|
142
+ count += 1
143
+ if count >= 10
144
+ raise Timeout::Error
145
+ end
146
+ sleeps.push(t)
147
+ }
148
+
149
+ Timeout.stub(:timeout) { |&block|
150
+ block.call
151
+ }
152
+ expect(Timeout).to receive(:timeout).at_least(1).times
153
+
154
+ expect(-> { subject.publish({event: 'explode', uid: 'thing:rspec$1'})}).to raise_error do |e|
155
+ e.should be Pebbles::River::SendFailure
156
+ e.exception.should be exception_class
157
+ end
158
+
159
+ expect(sleeps[0, 9]).to eq [1, 2, 4, 8, 10, 10, 10, 10, 10]
140
160
  end
141
161
  end
142
162
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pebbles-river
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Staubo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-15 00:00:00.000000000 Z
12
+ date: 2014-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pebblebed
@@ -137,6 +137,7 @@ files:
137
137
  - Rakefile
138
138
  - lib/pebbles/river.rb
139
139
  - lib/pebbles/river/compatibility.rb
140
+ - lib/pebbles/river/errors.rb
140
141
  - lib/pebbles/river/message.rb
141
142
  - lib/pebbles/river/river.rb
142
143
  - lib/pebbles/river/routing.rb