rapns 3.2.0 → 3.3.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/CHANGELOG.md +5 -0
- data/README.md +9 -18
- data/lib/generators/templates/rapns.rb +5 -0
- data/lib/rapns.rb +4 -0
- data/lib/rapns/apns_feedback.rb +1 -0
- data/lib/rapns/configuration.rb +4 -3
- data/lib/rapns/daemon.rb +20 -4
- data/lib/rapns/daemon/apns/feedback_receiver.rb +9 -11
- data/lib/rapns/daemon/delivery.rb +3 -20
- data/lib/rapns/daemon/delivery_queue.rb +2 -2
- data/lib/rapns/daemon/feeder.rb +5 -10
- data/lib/rapns/daemon/gcm/delivery.rb +19 -9
- data/lib/rapns/daemon/store/active_record.rb +74 -0
- data/lib/rapns/daemon/store/active_record/reconnectable.rb +61 -0
- data/lib/rapns/gcm/notification.rb +5 -4
- data/lib/rapns/gcm/registration_ids_count_validator.rb +1 -1
- data/lib/rapns/logger.rb +6 -2
- data/lib/rapns/push.rb +1 -0
- data/lib/rapns/reflection.rb +1 -1
- data/lib/rapns/version.rb +1 -1
- data/spec/unit/apns/notification_spec.rb +2 -0
- data/spec/unit/apns_feedback_spec.rb +5 -0
- data/spec/unit/configuration_spec.rb +1 -1
- data/spec/unit/daemon/apns/delivery_spec.rb +7 -64
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +2 -2
- data/spec/unit/daemon/feeder_spec.rb +6 -58
- data/spec/unit/daemon/gcm/delivery_spec.rb +49 -57
- data/spec/unit/daemon/{database_reconnectable_spec.rb → store/active_record/reconnectable_spec.rb} +4 -3
- data/spec/unit/daemon/store/active_record_spec.rb +181 -0
- data/spec/unit/daemon_spec.rb +27 -7
- data/spec/unit/gcm/notification_spec.rb +2 -9
- data/spec/unit/push_spec.rb +5 -0
- data/spec/unit/reflection_spec.rb +0 -4
- data/spec/unit_spec_helper.rb +4 -1
- metadata +10 -7
- data/lib/rapns/daemon/database_reconnectable.rb +0 -57
data/spec/unit/daemon/{database_reconnectable_spec.rb → store/active_record/reconnectable_spec.rb}
RENAMED
@@ -1,8 +1,9 @@
|
|
1
|
-
require
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'rapns/daemon/store/active_record/reconnectable'
|
2
3
|
|
3
|
-
describe Rapns::Daemon::
|
4
|
+
describe Rapns::Daemon::Store::ActiveRecord::Reconnectable do
|
4
5
|
class TestDouble
|
5
|
-
include Rapns::Daemon::
|
6
|
+
include Rapns::Daemon::Store::ActiveRecord::Reconnectable
|
6
7
|
|
7
8
|
attr_reader :name
|
8
9
|
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'rapns/daemon/store/active_record'
|
3
|
+
|
4
|
+
describe Rapns::Daemon::Store::ActiveRecord do
|
5
|
+
let(:app) { Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
|
6
|
+
let(:notification) { Rapns::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
|
7
|
+
let(:store) { Rapns::Daemon::Store::ActiveRecord.new }
|
8
|
+
let(:now) { Time.now }
|
9
|
+
|
10
|
+
before { Time.stub(:now => now) }
|
11
|
+
|
12
|
+
describe 'deliverable_notifications' do
|
13
|
+
it 'checks for new notifications with the ability to reconnect the database' do
|
14
|
+
store.should_receive(:with_database_reconnect_and_retry)
|
15
|
+
store.deliverable_notifications(app)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'loads notifications in batches' do
|
19
|
+
Rapns.config.batch_size = 5000
|
20
|
+
Rapns.config.push = false
|
21
|
+
relation = stub.as_null_object
|
22
|
+
relation.should_receive(:limit).with(5000)
|
23
|
+
Rapns::Notification.stub(:ready_for_delivery => relation)
|
24
|
+
store.deliverable_notifications([app])
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does not load notification in batches if in push mode' do
|
28
|
+
Rapns.config.push = true
|
29
|
+
relation = stub.as_null_object
|
30
|
+
relation.should_not_receive(:limit)
|
31
|
+
Rapns::Notification.stub(:ready_for_delivery => relation)
|
32
|
+
store.deliverable_notifications([app])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'loads an undelivered notification without deliver_after set' do
|
36
|
+
notification.update_attributes!(:delivered => false, :deliver_after => nil)
|
37
|
+
store.deliverable_notifications([app]).should == [notification]
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'loads an notification with a deliver_after time in the past' do
|
41
|
+
notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
|
42
|
+
store.deliverable_notifications([app]).should == [notification]
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'does not load an notification with a deliver_after time in the future' do
|
46
|
+
notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
|
47
|
+
store.deliverable_notifications([app]).should be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'does not load a previously delivered notification' do
|
51
|
+
notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
|
52
|
+
store.deliverable_notifications([app]).should be_empty
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does not enqueue a notification that has previously failed delivery" do
|
56
|
+
notification.update_attributes!(:delivered => false, :failed => true)
|
57
|
+
store.deliverable_notifications([app]).should be_empty
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'does not load notifications for apps that are still processing the previous batch' do
|
61
|
+
notification
|
62
|
+
store.deliverable_notifications([]).should be_empty
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'retry_after' do
|
67
|
+
it 'increments the retry count' do
|
68
|
+
expect do
|
69
|
+
store.retry_after(notification, now)
|
70
|
+
end.to change(notification, :retries).by(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'sets the deliver after timestamp' do
|
74
|
+
deliver_after = now + 10.seconds
|
75
|
+
expect do
|
76
|
+
store.retry_after(notification, deliver_after)
|
77
|
+
end.to change(notification, :deliver_after).to(deliver_after)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'saves the notification without validation' do
|
81
|
+
notification.should_receive(:save!).with(:validate => false)
|
82
|
+
store.retry_after(notification, now)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'mark_delivered' do
|
87
|
+
it 'marks the notification as delivered' do
|
88
|
+
expect do
|
89
|
+
store.mark_delivered(notification)
|
90
|
+
end.to change(notification, :delivered).to(true)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'sets the time the notification was delivered' do
|
94
|
+
expect do
|
95
|
+
store.mark_delivered(notification)
|
96
|
+
end.to change(notification, :delivered_at).to(now)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'saves the notification without validation' do
|
100
|
+
notification.should_receive(:save!).with(:validate => false)
|
101
|
+
store.mark_delivered(notification)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'mark_failed' do
|
106
|
+
it 'marks the notification as not delivered' do
|
107
|
+
store.mark_failed(notification, nil, '')
|
108
|
+
notification.delivered.should be_false
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'marks the notification as failed' do
|
112
|
+
expect do
|
113
|
+
store.mark_failed(notification, nil, '')
|
114
|
+
end.to change(notification, :failed).to(true)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'sets the time the notification delivery failed' do
|
118
|
+
expect do
|
119
|
+
store.mark_failed(notification, nil, '')
|
120
|
+
end.to change(notification, :failed_at).to(now)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'sets the error code' do
|
124
|
+
expect do
|
125
|
+
store.mark_failed(notification, 42, '')
|
126
|
+
end.to change(notification, :error_code).to(42)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'sets the error description' do
|
130
|
+
expect do
|
131
|
+
store.mark_failed(notification, 42, 'Weeee')
|
132
|
+
end.to change(notification, :error_description).to('Weeee')
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'saves the notification without validation' do
|
136
|
+
notification.should_receive(:save!).with(:validate => false)
|
137
|
+
store.mark_failed(notification, nil, '')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'create_apns_feedback' do
|
142
|
+
it 'creates the Feedback record' do
|
143
|
+
Rapns::Apns::Feedback.should_receive(:create!).with(
|
144
|
+
:failed_at => now, :device_token => 'ab' * 32, :app => app)
|
145
|
+
store.create_apns_feedback(now, 'ab' * 32, app)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'create_gcm_notification' do
|
150
|
+
let(:data) { { :data => true } }
|
151
|
+
let(:attributes) { { :device_token => 'ab' * 32 } }
|
152
|
+
let(:registration_ids) { ['123', '456'] }
|
153
|
+
let(:deliver_after) { now + 10.seconds }
|
154
|
+
let(:args) { [attributes, data, registration_ids, deliver_after, app] }
|
155
|
+
|
156
|
+
it 'sets the given attributes' do
|
157
|
+
new_notification = store.create_gcm_notification(*args)
|
158
|
+
new_notification.device_token.should == 'ab' * 32
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'sets the given data' do
|
162
|
+
new_notification = store.create_gcm_notification(*args)
|
163
|
+
new_notification.data['data'].should be_true
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'sets the given registration IDs' do
|
167
|
+
new_notification = store.create_gcm_notification(*args)
|
168
|
+
new_notification.registration_ids.should == registration_ids
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'sets the deliver_after timestamp' do
|
172
|
+
new_notification = store.create_gcm_notification(*args)
|
173
|
+
new_notification.deliver_after.should == deliver_after
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'saves the new notification' do
|
177
|
+
new_notification = store.create_gcm_notification(*args)
|
178
|
+
new_notification.new_record?.should be_false
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/spec/unit/daemon_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
|
+
require 'rapns/daemon/store/active_record'
|
2
3
|
|
3
4
|
describe Rapns::Daemon, "when starting" do
|
4
5
|
module Rails; end
|
@@ -6,27 +7,34 @@ describe Rapns::Daemon, "when starting" do
|
|
6
7
|
let(:certificate) { stub }
|
7
8
|
let(:password) { stub }
|
8
9
|
let(:config) { stub(:pid_file => nil, :airbrake_notify => false,
|
9
|
-
:foreground => true, :embedded => false, :push => false) }
|
10
|
+
:foreground => true, :embedded => false, :push => false, :store => :active_record) }
|
10
11
|
let(:logger) { stub(:logger, :info => nil, :error => nil, :warn => nil) }
|
11
12
|
|
12
13
|
before do
|
13
|
-
Rapns.stub(:config => config)
|
14
|
-
Rapns::Logger.stub(:new => logger)
|
14
|
+
Rapns.stub(:config => config, :logger => logger)
|
15
15
|
Rapns::Daemon::Feeder.stub(:start)
|
16
16
|
Rapns::Daemon::AppRunner.stub(:sync => nil, :stop => nil)
|
17
|
-
Rapns::Daemon.stub(:daemonize => nil, :
|
17
|
+
Rapns::Daemon.stub(:daemonize => nil, :exit => nil, :puts => nil)
|
18
18
|
File.stub(:open)
|
19
19
|
Rails.stub(:root).and_return("/rails_root")
|
20
20
|
end
|
21
21
|
|
22
|
-
unless
|
22
|
+
unless Rapns.jruby?
|
23
23
|
it "forks into a daemon if the foreground option is false" do
|
24
24
|
config.stub(:foreground => false)
|
25
|
-
|
25
|
+
Rapns::Daemon.initialize_store
|
26
|
+
Rapns::Daemon.store.stub(:after_daemonize => nil)
|
26
27
|
Rapns::Daemon.should_receive(:daemonize)
|
27
28
|
Rapns::Daemon.start
|
28
29
|
end
|
29
30
|
|
31
|
+
it 'notifies the store after forking' do
|
32
|
+
config.stub(:foreground => false)
|
33
|
+
Rapns::Daemon.initialize_store
|
34
|
+
Rapns::Daemon.store.should_receive(:after_daemonize)
|
35
|
+
Rapns::Daemon.start
|
36
|
+
end
|
37
|
+
|
30
38
|
it "does not fork into a daemon if the foreground option is true" do
|
31
39
|
config.stub(:foreground => true)
|
32
40
|
Rapns::Daemon.should_not_receive(:daemonize)
|
@@ -57,6 +65,18 @@ describe Rapns::Daemon, "when starting" do
|
|
57
65
|
Rapns::Daemon.start
|
58
66
|
end
|
59
67
|
|
68
|
+
it 'instantiates the store' do
|
69
|
+
config.stub(:store => :active_record)
|
70
|
+
Rapns::Daemon.start
|
71
|
+
Rapns::Daemon.store.should be_kind_of(Rapns::Daemon::Store::ActiveRecord)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'logs an error if the store cannot be loaded' do
|
75
|
+
config.stub(:store => :foo_bar)
|
76
|
+
Rapns.logger.should_receive(:error).with(kind_of(LoadError))
|
77
|
+
Rapns::Daemon.start
|
78
|
+
end
|
79
|
+
|
60
80
|
it "writes the process ID to the PID file" do
|
61
81
|
Rapns::Daemon.should_receive(:write_pid_file)
|
62
82
|
Rapns::Daemon.start
|
@@ -91,7 +111,7 @@ describe Rapns::Daemon, "when being shutdown" do
|
|
91
111
|
end
|
92
112
|
|
93
113
|
# These tests do not work on JRuby.
|
94
|
-
unless
|
114
|
+
unless Rapns.jruby?
|
95
115
|
it "shuts down when signaled signaled SIGINT" do
|
96
116
|
Rapns::Daemon.setup_signal_traps
|
97
117
|
Rapns::Daemon.should_receive(:shutdown)
|
@@ -27,7 +27,7 @@ describe Rapns::Gcm::Notification do
|
|
27
27
|
it 'num of registration Ids limit of 1000' do
|
28
28
|
notification.registration_ids = ['a']*(1000+1)
|
29
29
|
notification.valid?.should be_false
|
30
|
-
notification.errors[:base].should == ["GCM notification
|
30
|
+
notification.errors[:base].should == ["GCM notification number of registration_ids cannot be larger than 1000."]
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'allows assignment of a single registration ID' do
|
@@ -45,15 +45,8 @@ describe Rapns::Gcm::Notification do
|
|
45
45
|
notification.errors[:expiry].should == ['must be set when using a collapse_key']
|
46
46
|
end
|
47
47
|
|
48
|
-
it '
|
48
|
+
it 'includes time_to_live in the payload' do
|
49
49
|
notification.expiry = 100
|
50
|
-
notification.collapse_key = nil
|
51
|
-
notification.as_json.key?('time_to_live').should be_false
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'includes time_to_live in the payload if collapse_key is set' do
|
55
|
-
notification.expiry = 100
|
56
|
-
notification.collapse_key = 'sync'
|
57
50
|
notification.as_json['time_to_live'].should == 100
|
58
51
|
end
|
59
52
|
end
|
data/spec/unit/push_spec.rb
CHANGED
@@ -12,6 +12,11 @@ describe Rapns, 'push' do
|
|
12
12
|
Rapns.config.push.should be_true
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'initializes the store' do
|
16
|
+
Rapns::Daemon.should_receive(:initialize_store)
|
17
|
+
Rapns.push
|
18
|
+
end
|
19
|
+
|
15
20
|
it 'syncs the app runner' do
|
16
21
|
Rapns::Daemon::AppRunner.should_receive(:sync)
|
17
22
|
Rapns.push
|
@@ -12,10 +12,6 @@ describe Rapns do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
# :apns_feedback, :notification_enqueued, :notification_delivered,
|
16
|
-
# :notification_failed, :notification_will_retry, :apns_connection_lost,
|
17
|
-
# :error
|
18
|
-
|
19
15
|
describe Rapns::Reflections do
|
20
16
|
it 'dispatches the given reflection' do
|
21
17
|
did_yield = false
|
data/spec/unit_spec_helper.rb
CHANGED
@@ -72,7 +72,10 @@ RSpec.configure do |config|
|
|
72
72
|
DatabaseCleaner.clean
|
73
73
|
end
|
74
74
|
|
75
|
-
config.after(:each)
|
75
|
+
config.after(:each) do
|
76
|
+
Rapns.logger = nil
|
77
|
+
Rapns::Daemon.store = nil
|
78
|
+
end
|
76
79
|
end
|
77
80
|
|
78
81
|
# a test certificate that contains both an X509 certificate and
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rapns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.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: 2013-04-
|
12
|
+
date: 2013-04-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -80,7 +80,6 @@ files:
|
|
80
80
|
- lib/rapns/daemon/apns/disconnection_error.rb
|
81
81
|
- lib/rapns/daemon/apns/feedback_receiver.rb
|
82
82
|
- lib/rapns/daemon/app_runner.rb
|
83
|
-
- lib/rapns/daemon/database_reconnectable.rb
|
84
83
|
- lib/rapns/daemon/delivery.rb
|
85
84
|
- lib/rapns/daemon/delivery_error.rb
|
86
85
|
- lib/rapns/daemon/delivery_handler.rb
|
@@ -93,6 +92,8 @@ files:
|
|
93
92
|
- lib/rapns/daemon/gcm/delivery_handler.rb
|
94
93
|
- lib/rapns/daemon/interruptible_sleep.rb
|
95
94
|
- lib/rapns/daemon/reflectable.rb
|
95
|
+
- lib/rapns/daemon/store/active_record.rb
|
96
|
+
- lib/rapns/daemon/store/active_record/reconnectable.rb
|
96
97
|
- lib/rapns/deprecatable.rb
|
97
98
|
- lib/rapns/deprecation.rb
|
98
99
|
- lib/rapns/embed.rb
|
@@ -134,7 +135,6 @@ files:
|
|
134
135
|
- spec/unit/daemon/apns/feedback_receiver_spec.rb
|
135
136
|
- spec/unit/daemon/app_runner_shared.rb
|
136
137
|
- spec/unit/daemon/app_runner_spec.rb
|
137
|
-
- spec/unit/daemon/database_reconnectable_spec.rb
|
138
138
|
- spec/unit/daemon/delivery_error_spec.rb
|
139
139
|
- spec/unit/daemon/delivery_handler_shared.rb
|
140
140
|
- spec/unit/daemon/delivery_queue_spec.rb
|
@@ -144,6 +144,8 @@ files:
|
|
144
144
|
- spec/unit/daemon/gcm/delivery_spec.rb
|
145
145
|
- spec/unit/daemon/interruptible_sleep_spec.rb
|
146
146
|
- spec/unit/daemon/reflectable_spec.rb
|
147
|
+
- spec/unit/daemon/store/active_record/reconnectable_spec.rb
|
148
|
+
- spec/unit/daemon/store/active_record_spec.rb
|
147
149
|
- spec/unit/daemon_spec.rb
|
148
150
|
- spec/unit/deprecatable_spec.rb
|
149
151
|
- spec/unit/deprecation_spec.rb
|
@@ -173,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
173
175
|
version: '0'
|
174
176
|
segments:
|
175
177
|
- 0
|
176
|
-
hash: -
|
178
|
+
hash: -3085387548794744992
|
177
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
180
|
none: false
|
179
181
|
requirements:
|
@@ -182,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
184
|
version: '0'
|
183
185
|
segments:
|
184
186
|
- 0
|
185
|
-
hash: -
|
187
|
+
hash: -3085387548794744992
|
186
188
|
requirements: []
|
187
189
|
rubyforge_project:
|
188
190
|
rubygems_version: 1.8.25
|
@@ -211,7 +213,6 @@ test_files:
|
|
211
213
|
- spec/unit/daemon/apns/feedback_receiver_spec.rb
|
212
214
|
- spec/unit/daemon/app_runner_shared.rb
|
213
215
|
- spec/unit/daemon/app_runner_spec.rb
|
214
|
-
- spec/unit/daemon/database_reconnectable_spec.rb
|
215
216
|
- spec/unit/daemon/delivery_error_spec.rb
|
216
217
|
- spec/unit/daemon/delivery_handler_shared.rb
|
217
218
|
- spec/unit/daemon/delivery_queue_spec.rb
|
@@ -221,6 +222,8 @@ test_files:
|
|
221
222
|
- spec/unit/daemon/gcm/delivery_spec.rb
|
222
223
|
- spec/unit/daemon/interruptible_sleep_spec.rb
|
223
224
|
- spec/unit/daemon/reflectable_spec.rb
|
225
|
+
- spec/unit/daemon/store/active_record/reconnectable_spec.rb
|
226
|
+
- spec/unit/daemon/store/active_record_spec.rb
|
224
227
|
- spec/unit/daemon_spec.rb
|
225
228
|
- spec/unit/deprecatable_spec.rb
|
226
229
|
- spec/unit/deprecation_spec.rb
|
@@ -1,57 +0,0 @@
|
|
1
|
-
class PGError < StandardError; end if !defined?(PGError)
|
2
|
-
class Mysql; class Error < StandardError; end; end if !defined?(Mysql)
|
3
|
-
module Mysql2; class Error < StandardError; end; end if !defined?(Mysql2)
|
4
|
-
module ActiveRecord; end
|
5
|
-
class ActiveRecord::JDBCError < StandardError; end if !defined?(ActiveRecord::JDBCError)
|
6
|
-
|
7
|
-
module Rapns
|
8
|
-
module Daemon
|
9
|
-
module DatabaseReconnectable
|
10
|
-
ADAPTER_ERRORS = [ActiveRecord::StatementInvalid, PGError, Mysql::Error,
|
11
|
-
Mysql2::Error, ActiveRecord::JDBCError]
|
12
|
-
|
13
|
-
def with_database_reconnect_and_retry
|
14
|
-
begin
|
15
|
-
ActiveRecord::Base.connection_pool.with_connection do
|
16
|
-
yield
|
17
|
-
end
|
18
|
-
rescue *ADAPTER_ERRORS => e
|
19
|
-
Rapns.logger.error(e)
|
20
|
-
database_connection_lost
|
21
|
-
retry
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def database_connection_lost
|
26
|
-
Rapns.logger.warn("Lost connection to database, reconnecting...")
|
27
|
-
attempts = 0
|
28
|
-
loop do
|
29
|
-
begin
|
30
|
-
Rapns.logger.warn("Attempt #{attempts += 1}")
|
31
|
-
reconnect_database
|
32
|
-
check_database_is_connected
|
33
|
-
break
|
34
|
-
rescue *ADAPTER_ERRORS => e
|
35
|
-
Rapns.logger.error(e, :airbrake_notify => false)
|
36
|
-
sleep_to_avoid_thrashing
|
37
|
-
end
|
38
|
-
end
|
39
|
-
Rapns.logger.warn("Database reconnected")
|
40
|
-
end
|
41
|
-
|
42
|
-
def reconnect_database
|
43
|
-
ActiveRecord::Base.clear_all_connections!
|
44
|
-
ActiveRecord::Base.establish_connection
|
45
|
-
end
|
46
|
-
|
47
|
-
def check_database_is_connected
|
48
|
-
# Simply asking the adapter for the connection state is not sufficient.
|
49
|
-
Rapns::Notification.count
|
50
|
-
end
|
51
|
-
|
52
|
-
def sleep_to_avoid_thrashing
|
53
|
-
sleep 2
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|