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 +4 -4
- data/lib/pebbles/river/errors.rb +17 -0
- data/lib/pebbles/river/river.rb +34 -25
- data/lib/pebbles/river/version.rb +1 -1
- data/lib/pebbles/river.rb +1 -0
- data/spec/lib/river_spec.rb +25 -5
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32827f1f43724f8f2d5cf53943d89b519be5be11
|
4
|
+
data.tar.gz: 38db2f8b16ea69ca288e4f5c26c5debe1556356a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/pebbles/river/river.rb
CHANGED
@@ -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
|
-
|
32
|
-
|
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
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
data/lib/pebbles/river.rb
CHANGED
data/spec/lib/river_spec.rb
CHANGED
@@ -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 "
|
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
|
-
|
139
|
-
|
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.
|
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-
|
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
|