rapns_rails_2 3.5.1 → 3.6.1
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.
- checksums.yaml +7 -0
- data/README.md +2 -0
- data/lib/rapns/daemon/gcm/delivery.rb +4 -3
- data/lib/rapns/version.rb +1 -1
- metadata +46 -163
- data/config/database.yml +0 -44
- data/spec/support/cert_with_password.pem +0 -90
- data/spec/support/cert_without_password.pem +0 -59
- data/spec/support/simplecov_helper.rb +0 -13
- data/spec/support/simplecov_quality_formatter.rb +0 -8
- data/spec/tmp/.gitkeep +0 -0
- data/spec/unit/apns/app_spec.rb +0 -29
- data/spec/unit/apns/feedback_spec.rb +0 -9
- data/spec/unit/apns/notification_spec.rb +0 -215
- data/spec/unit/apns_feedback_spec.rb +0 -21
- data/spec/unit/app_spec.rb +0 -16
- data/spec/unit/configuration_spec.rb +0 -55
- data/spec/unit/daemon/apns/app_runner_spec.rb +0 -45
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +0 -11
- data/spec/unit/daemon/apns/connection_spec.rb +0 -287
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +0 -59
- data/spec/unit/daemon/apns/delivery_spec.rb +0 -101
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +0 -134
- data/spec/unit/daemon/app_runner_shared.rb +0 -83
- data/spec/unit/daemon/app_runner_spec.rb +0 -170
- data/spec/unit/daemon/batch_spec.rb +0 -219
- data/spec/unit/daemon/delivery_error_spec.rb +0 -13
- data/spec/unit/daemon/delivery_handler_collection_spec.rb +0 -37
- data/spec/unit/daemon/delivery_handler_shared.rb +0 -45
- data/spec/unit/daemon/feeder_spec.rb +0 -89
- data/spec/unit/daemon/gcm/app_runner_spec.rb +0 -19
- data/spec/unit/daemon/gcm/delivery_handler_spec.rb +0 -44
- data/spec/unit/daemon/gcm/delivery_spec.rb +0 -289
- data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
- data/spec/unit/daemon/reflectable_spec.rb +0 -27
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +0 -114
- data/spec/unit/daemon/store/active_record_spec.rb +0 -281
- data/spec/unit/daemon_spec.rb +0 -157
- data/spec/unit/deprecatable_spec.rb +0 -32
- data/spec/unit/deprecation_spec.rb +0 -15
- data/spec/unit/embed_spec.rb +0 -50
- data/spec/unit/gcm/app_spec.rb +0 -4
- data/spec/unit/gcm/notification_spec.rb +0 -52
- data/spec/unit/logger_spec.rb +0 -180
- data/spec/unit/notification_shared.rb +0 -45
- data/spec/unit/notification_spec.rb +0 -4
- data/spec/unit/notifier_spec.rb +0 -52
- data/spec/unit/push_spec.rb +0 -44
- data/spec/unit/rapns_spec.rb +0 -9
- data/spec/unit/reflection_spec.rb +0 -30
- data/spec/unit/upgraded_spec.rb +0 -40
- data/spec/unit_spec_helper.rb +0 -137
@@ -1,289 +0,0 @@
|
|
1
|
-
require File.expand_path("spec/unit_spec_helper")
|
2
|
-
|
3
|
-
describe Rapns::Daemon::Gcm::Delivery do
|
4
|
-
let(:app) { Rapns::Gcm::App.new(:name => 'MyApp', :auth_key => 'abc123') }
|
5
|
-
let(:notification) { Rapns::Gcm::Notification.create!(:app => app, :registration_ids => ['xyz'], :deliver_after => Time.now) }
|
6
|
-
let(:logger) { double(:error => nil, :info => nil, :warn => nil) }
|
7
|
-
let(:response) { double(:code => 200, :header => {}) }
|
8
|
-
let(:http) { double(:shutdown => nil, :request => response)}
|
9
|
-
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
10
|
-
let(:batch) { double(:mark_failed => nil, :mark_delivered => nil, :mark_retryable => nil) }
|
11
|
-
let(:delivery) { Rapns::Daemon::Gcm::Delivery.new(app, http, notification, batch) }
|
12
|
-
let(:store) { double(:create_gcm_notification => double(:id => 2)) }
|
13
|
-
|
14
|
-
def perform
|
15
|
-
delivery.perform
|
16
|
-
end
|
17
|
-
|
18
|
-
before do
|
19
|
-
delivery.stub(:reflect => nil)
|
20
|
-
Rapns::Daemon.stub(:store => store)
|
21
|
-
Time.stub(:now => now)
|
22
|
-
Rapns.stub(:logger => logger)
|
23
|
-
end
|
24
|
-
|
25
|
-
shared_examples_for 'an notification with some delivery failures' do
|
26
|
-
let(:new_notification) { Rapns::Gcm::Notification.where('id != ?', notification.id).first }
|
27
|
-
|
28
|
-
before { response.stub(:body => MultiJson.dump(body) ) }
|
29
|
-
|
30
|
-
it 'marks the original notification as failed' do
|
31
|
-
batch.should_receive(:mark_failed).with(notification, nil, error_description)
|
32
|
-
perform rescue Rapns::DeliveryError
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'creates a new notification for the unavailable devices' do
|
36
|
-
notification.update_attributes(:registration_ids => ['id_0', 'id_1', 'id_2'], :data => {'one' => 1}, :collapse_key => 'thing', :delay_while_idle => true)
|
37
|
-
response.stub(:header => { 'retry-after' => 10 })
|
38
|
-
attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
|
39
|
-
store.should_receive(:create_gcm_notification).with(attrs, notification.data,
|
40
|
-
['id_0', 'id_2'], now + 10.seconds, notification.app)
|
41
|
-
perform rescue Rapns::DeliveryError
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'raises a DeliveryError' do
|
45
|
-
expect { perform }.to raise_error(Rapns::DeliveryError)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe 'an 200 response' do
|
50
|
-
before do
|
51
|
-
response.stub(:code => 200)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'marks the notification as delivered if delivered successfully to all devices' do
|
55
|
-
response.stub(:body => MultiJson.dump({ 'failure' => 0 }))
|
56
|
-
batch.should_receive(:mark_delivered).with(notification)
|
57
|
-
perform
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'logs that the notification was delivered' do
|
61
|
-
response.stub(:body => MultiJson.dump({ 'failure' => 0 }))
|
62
|
-
logger.should_receive(:info).with("[MyApp] #{notification.id} sent to xyz")
|
63
|
-
perform
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'marks a notification as failed if any deliveries failed that cannot be retried.' do
|
67
|
-
body = {
|
68
|
-
'failure' => 1,
|
69
|
-
'success' => 1,
|
70
|
-
'results' => [
|
71
|
-
{ 'message_id' => '1:000' },
|
72
|
-
{ 'error' => 'InvalidDataKey' }
|
73
|
-
]}
|
74
|
-
response.stub(:body => MultiJson.dump(body))
|
75
|
-
batch.should_receive(:mark_failed).with(notification, nil, "Failed to deliver to all recipients. Errors: InvalidDataKey.")
|
76
|
-
perform rescue Rapns::DeliveryError
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'reflects on canonical IDs' do
|
80
|
-
body = {
|
81
|
-
'failure' => 0,
|
82
|
-
'success' => 3,
|
83
|
-
'canonical_ids' => 1,
|
84
|
-
'results' => [
|
85
|
-
{ 'message_id' => '1:000' },
|
86
|
-
{ 'message_id' => '1:000', 'registration_id' => 'canonical123' },
|
87
|
-
{ 'message_id' => '1:000' },
|
88
|
-
]}
|
89
|
-
|
90
|
-
response.stub(:body => MultiJson.dump(body))
|
91
|
-
notification.stub(:registration_ids => ['1', '2', '3'])
|
92
|
-
delivery.should_receive(:reflect).with(:gcm_canonical_id, '2', 'canonical123')
|
93
|
-
perform
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'reflects on invalid IDs' do
|
97
|
-
body = {
|
98
|
-
'failure' => 1,
|
99
|
-
'success' => 2,
|
100
|
-
'canonical_ids' => 0,
|
101
|
-
'results' => [
|
102
|
-
{ 'message_id' => '1:000' },
|
103
|
-
{ 'error' => 'NotRegistered' },
|
104
|
-
{ 'message_id' => '1:000' },
|
105
|
-
]}
|
106
|
-
|
107
|
-
response.stub(:body => MultiJson.dump(body))
|
108
|
-
notification.stub(:registration_ids => ['1', '2', '3'])
|
109
|
-
delivery.should_receive(:reflect).with(:gcm_invalid_registration_id, app, 'NotRegistered', '2')
|
110
|
-
perform
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'does marks a notification as failed if any ids are invalid.' do
|
114
|
-
body = {
|
115
|
-
'failure' => 1,
|
116
|
-
'success' => 2,
|
117
|
-
'canonical_ids' => 0,
|
118
|
-
'results' => [
|
119
|
-
{ 'message_id' => '1:000' },
|
120
|
-
{ 'error' => 'NotRegistered' },
|
121
|
-
{ 'message_id' => '1:000' },
|
122
|
-
]}
|
123
|
-
|
124
|
-
response.stub(:body => MultiJson.dump(body))
|
125
|
-
batch.should_receive(:mark_failed)
|
126
|
-
batch.should_not_receive(:mark_retryable)
|
127
|
-
store.should_not_receive(:create_gcm_notification)
|
128
|
-
perform
|
129
|
-
end
|
130
|
-
|
131
|
-
describe 'all deliveries returned Unavailable or InternalServerError' do
|
132
|
-
let(:body) {{
|
133
|
-
'failure' => 2,
|
134
|
-
'success' => 0,
|
135
|
-
'results' => [
|
136
|
-
{ 'error' => 'Unavailable' },
|
137
|
-
{ 'error' => 'Unavailable' }
|
138
|
-
]}}
|
139
|
-
|
140
|
-
before { response.stub(:body => MultiJson.dump(body)) }
|
141
|
-
|
142
|
-
it 'retries the notification respecting the Retry-After header' do
|
143
|
-
response.stub(:header => { 'retry-after' => 10 })
|
144
|
-
batch.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
145
|
-
perform
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'retries the notification using exponential back-off if the Retry-After header is not present' do
|
149
|
-
batch.should_receive(:mark_retryable).with(notification, now + 2)
|
150
|
-
perform
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'does not mark the notification as failed' do
|
154
|
-
batch.should_not_receive(:mark_failed)
|
155
|
-
perform
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'logs that the notification will be retried' do
|
159
|
-
notification.retries = 1
|
160
|
-
notification.deliver_after = now + 2
|
161
|
-
Rapns.logger.should_receive(:warn).with("All recipients unavailable. Notification #{notification.id} will be retried after 2012-10-14 00:00:02 (retry 1).")
|
162
|
-
perform
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
shared_examples_for 'an notification with some delivery failures (200)' do
|
167
|
-
let(:new_notification) { Rapns::Gcm::Notification.where('id != ?', notification.id).first }
|
168
|
-
|
169
|
-
before { response.stub(:body => MultiJson.dump(body)) }
|
170
|
-
|
171
|
-
it 'marks the original notification as failed' do
|
172
|
-
batch.should_receive(:mark_failed).with(notification, nil, error_description)
|
173
|
-
perform rescue Rapns::DeliveryError
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'creates a new notification for the unavailable devices' do
|
177
|
-
notification.update_attributes(:registration_ids => ['id_0', 'id_1', 'id_2'], :data => {'one' => 1}, :collapse_key => 'thing', :delay_while_idle => true)
|
178
|
-
response.stub(:header => { 'retry-after' => 10 })
|
179
|
-
attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
|
180
|
-
store.should_receive(:create_gcm_notification).with(attrs, notification.data,
|
181
|
-
['id_0', 'id_2'], now + 10.seconds, notification.app)
|
182
|
-
perform rescue Rapns::DeliveryError
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'raises a DeliveryError' do
|
186
|
-
expect { perform }.to raise_error(Rapns::DeliveryError)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
describe 'all deliveries failed with some as Unavailable or InternalServerError' do
|
191
|
-
let(:body) {{
|
192
|
-
'failure' => 3,
|
193
|
-
'success' => 0,
|
194
|
-
'results' => [
|
195
|
-
{ 'error' => 'Unavailable' },
|
196
|
-
{ 'error' => 'InvalidDataKey' },
|
197
|
-
{ 'error' => 'Unavailable' }
|
198
|
-
]}}
|
199
|
-
let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 1, 2. Errors: Unavailable, InvalidDataKey, Unavailable. 0, 2 will be retried as notification")} [\d]+\./ }
|
200
|
-
it_should_behave_like 'an notification with some delivery failures (200)'
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
describe 'some deliveries failed with Unavailable or InternalServerError' do
|
205
|
-
let(:body) {{
|
206
|
-
'failure' => 2,
|
207
|
-
'success' => 1,
|
208
|
-
'results' => [
|
209
|
-
{ 'error' => 'Unavailable' },
|
210
|
-
{ 'message_id' => '1:000' },
|
211
|
-
{ 'error' => 'InternalServerError' }
|
212
|
-
]}}
|
213
|
-
let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 2. Errors: Unavailable, InternalServerError. 0, 2 will be retried as notification")} [\d]+\./ }
|
214
|
-
it_should_behave_like 'an notification with some delivery failures'
|
215
|
-
end
|
216
|
-
|
217
|
-
describe 'an 503 response' do
|
218
|
-
before { response.stub(:code => 503) }
|
219
|
-
|
220
|
-
it 'logs a warning that the notification will be retried.' do
|
221
|
-
notification.retries = 1
|
222
|
-
notification.deliver_after = now + 2
|
223
|
-
logger.should_receive(:warn).with("GCM responded with an Service Unavailable Error. Notification #{notification.id} will be retried after 2012-10-14 00:00:02 (retry 1).")
|
224
|
-
perform
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'respects an integer Retry-After header' do
|
228
|
-
response.stub(:header => { 'retry-after' => 10 })
|
229
|
-
batch.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
230
|
-
perform
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'respects a HTTP-date Retry-After header' do
|
234
|
-
response.stub(:header => { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
|
235
|
-
batch.should_receive(:mark_retryable).with(notification, Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
|
236
|
-
perform
|
237
|
-
end
|
238
|
-
|
239
|
-
it 'defaults to exponential back-off if the Retry-After header is not present' do
|
240
|
-
batch.should_receive(:mark_retryable).with(notification, now + 2 ** 1)
|
241
|
-
perform
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
describe 'an 500 response' do
|
246
|
-
before do
|
247
|
-
notification.update_attribute(:retries, 2)
|
248
|
-
response.stub(:code => 500)
|
249
|
-
end
|
250
|
-
|
251
|
-
it 'logs a warning that the notification has been re-queued.' do
|
252
|
-
notification.retries = 3
|
253
|
-
notification.deliver_after = now + 2 ** 3
|
254
|
-
Rapns.logger.should_receive(:warn).with("GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2 ** 3).strftime("%Y-%m-%d %H:%M:%S")} (retry 3).")
|
255
|
-
perform
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'retries the notification in accordance with the exponential back-off strategy.' do
|
259
|
-
batch.should_receive(:mark_retryable).with(notification, now + 2 ** 3)
|
260
|
-
perform
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
describe 'an 401 response' do
|
265
|
-
before { response.stub(:code => 401) }
|
266
|
-
|
267
|
-
it 'raises an error' do
|
268
|
-
expect { perform }.to raise_error(Rapns::DeliveryError)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
describe 'an 400 response' do
|
273
|
-
before { response.stub(:code => 400) }
|
274
|
-
|
275
|
-
it 'marks the notification as failed' do
|
276
|
-
batch.should_receive(:mark_failed).with(notification, 400, 'GCM failed to parse the JSON request. Possibly an rapns bug, please open an issue.')
|
277
|
-
perform rescue Rapns::DeliveryError
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
describe 'an un-handled response' do
|
282
|
-
before { response.stub(:code => 418) }
|
283
|
-
|
284
|
-
it 'marks the notification as failed' do
|
285
|
-
batch.should_receive(:mark_failed).with(notification, 418, "I'm a Teapot")
|
286
|
-
perform rescue Rapns::DeliveryError
|
287
|
-
end
|
288
|
-
end
|
289
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require File.expand_path("spec/unit_spec_helper")
|
2
|
-
|
3
|
-
describe Rapns::Daemon::InterruptibleSleep do
|
4
|
-
|
5
|
-
let(:rd) { double(:close => nil) }
|
6
|
-
let(:wr) { double(:close => nil) }
|
7
|
-
|
8
|
-
subject { Rapns::Daemon::InterruptibleSleep.new }
|
9
|
-
|
10
|
-
it 'creates a new pipe' do
|
11
|
-
IO.should_receive(:pipe)
|
12
|
-
subject
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'selects on the reader' do
|
16
|
-
IO.stub(:pipe => [rd, wr])
|
17
|
-
IO.should_receive(:select).with([rd], nil, nil, 1)
|
18
|
-
subject.sleep(1)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'closes the writer' do
|
22
|
-
IO.stub(:pipe => [rd, wr])
|
23
|
-
rd.should_receive(:close)
|
24
|
-
wr.should_receive(:close)
|
25
|
-
subject.close
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'returns false when timeout occurs' do
|
29
|
-
subject.sleep(0.01).should be_false
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'returns true when sleep does not timeout' do
|
33
|
-
subject.interrupt_sleep
|
34
|
-
subject.sleep(0.01).should be_true
|
35
|
-
end
|
36
|
-
|
37
|
-
context 'with UDP socket connected' do
|
38
|
-
before :each do
|
39
|
-
@host, @port = subject.enable_wake_on_udp('127.0.0.1', 0)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'times out with no udp activity' do
|
43
|
-
subject.sleep(0.01).should be_false
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'wakes on UDPSocket' do
|
47
|
-
waker = UDPSocket.new
|
48
|
-
waker.connect(@host, @port)
|
49
|
-
waker.write('x')
|
50
|
-
subject.sleep(0.01).should be_true
|
51
|
-
waker.close
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'consumes all data on udp socket' do
|
55
|
-
waker = UDPSocket.new
|
56
|
-
# waker.connect(@host, @port)
|
57
|
-
waker.send('x', 0, @host, @port)
|
58
|
-
waker.send('x', 0, @host, @port)
|
59
|
-
waker.send('x', 0, @host, @port)
|
60
|
-
# true since there is data to be read => no timeout
|
61
|
-
subject.sleep(0.01).should be_true
|
62
|
-
# false since data is consumed => wait for full timeout
|
63
|
-
subject.sleep(0.01).should be_false
|
64
|
-
waker.close
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require File.expand_path("spec/unit_spec_helper")
|
2
|
-
|
3
|
-
describe Rapns::Daemon::Reflectable do
|
4
|
-
class TestReflectable
|
5
|
-
include Rapns::Daemon::Reflectable
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:logger) { double(:error => nil) }
|
9
|
-
let(:test_reflectable) { TestReflectable.new }
|
10
|
-
|
11
|
-
before do
|
12
|
-
Rapns.reflections.stub(:__dispatch)
|
13
|
-
Rapns.stub(:logger => logger)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'dispatches the given reflection' do
|
17
|
-
Rapns.reflections.should_receive(:__dispatch).with(:error)
|
18
|
-
test_reflectable.reflect(:error)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'logs errors raise by the reflection' do
|
22
|
-
error = StandardError.new
|
23
|
-
Rapns.reflections.stub(:__dispatch).and_raise(error)
|
24
|
-
Rapns.logger.should_receive(:error).with(error)
|
25
|
-
test_reflectable.reflect(:error)
|
26
|
-
end
|
27
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
require File.expand_path("spec/unit_spec_helper")
|
2
|
-
require 'rapns/daemon/store/active_record/reconnectable'
|
3
|
-
|
4
|
-
describe Rapns::Daemon::Store::ActiveRecord::Reconnectable do
|
5
|
-
class TestDouble
|
6
|
-
include Rapns::Daemon::Store::ActiveRecord::Reconnectable
|
7
|
-
|
8
|
-
attr_reader :name
|
9
|
-
|
10
|
-
def initialize(error, max_calls)
|
11
|
-
@error = error
|
12
|
-
@max_calls = max_calls
|
13
|
-
@calls = 0
|
14
|
-
end
|
15
|
-
|
16
|
-
def perform
|
17
|
-
with_database_reconnect_and_retry do
|
18
|
-
@calls += 1
|
19
|
-
raise @error if @calls <= @max_calls
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
let(:adapter_error_class) do
|
25
|
-
case $adapter
|
26
|
-
when 'postgresql'
|
27
|
-
PGError
|
28
|
-
when 'mysql'
|
29
|
-
Mysql::Error
|
30
|
-
when 'mysql2'
|
31
|
-
Mysql2::Error
|
32
|
-
when 'jdbcpostgresql'
|
33
|
-
ActiveRecord::JDBCError
|
34
|
-
when 'jdbcmysql'
|
35
|
-
ActiveRecord::JDBCError
|
36
|
-
when 'jdbch2'
|
37
|
-
ActiveRecord::JDBCError
|
38
|
-
when 'sqlite3'
|
39
|
-
SQLite3::Exception
|
40
|
-
else
|
41
|
-
raise "Please update #{__FILE__} for adapter #{$adapter}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
let(:error) { adapter_error_class.new("db down!") }
|
45
|
-
let(:test_double) { TestDouble.new(error, 1) }
|
46
|
-
|
47
|
-
before do
|
48
|
-
@logger = double("Logger", :info => nil, :error => nil, :warn => nil)
|
49
|
-
Rapns.stub(:logger).and_return(@logger)
|
50
|
-
|
51
|
-
ActiveRecord::Base.stub(:clear_all_connections!)
|
52
|
-
ActiveRecord::Base.stub(:establish_connection)
|
53
|
-
test_double.stub(:sleep)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should log the error raised" do
|
57
|
-
Rapns.logger.should_receive(:error).with(error)
|
58
|
-
test_double.perform
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should log that the database is being reconnected" do
|
62
|
-
Rapns.logger.should_receive(:warn).with("Lost connection to database, reconnecting...")
|
63
|
-
test_double.perform
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should log the reconnection attempt" do
|
67
|
-
Rapns.logger.should_receive(:warn).with("Attempt 1")
|
68
|
-
test_double.perform
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should clear all connections" do
|
72
|
-
ActiveRecord::Base.should_receive(:clear_all_connections!)
|
73
|
-
test_double.perform
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should establish a new connection" do
|
77
|
-
ActiveRecord::Base.should_receive(:establish_connection)
|
78
|
-
test_double.perform
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should test out the new connection by performing a count" do
|
82
|
-
Rapns::Notification.should_receive(:count)
|
83
|
-
test_double.perform
|
84
|
-
end
|
85
|
-
|
86
|
-
context "when the reconnection attempt is not successful" do
|
87
|
-
before do
|
88
|
-
class << Rapns::Notification
|
89
|
-
def count
|
90
|
-
@count_calls += 1
|
91
|
-
return if @count_calls == 2
|
92
|
-
raise @error
|
93
|
-
end
|
94
|
-
end
|
95
|
-
Rapns::Notification.instance_variable_set("@count_calls", 0)
|
96
|
-
Rapns::Notification.instance_variable_set("@error", error)
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should log the 2nd attempt" do
|
100
|
-
Rapns.logger.should_receive(:warn).with("Attempt 2")
|
101
|
-
test_double.perform
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should log errors raised when the reconnection is not successful without notifying airbrake" do
|
105
|
-
Rapns.logger.should_receive(:error).with(error, :airbrake_notify => false)
|
106
|
-
test_double.perform
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should sleep to avoid thrashing when the database is down" do
|
110
|
-
test_double.should_receive(:sleep).with(2)
|
111
|
-
test_double.perform
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|