rpush 1.0.0-java → 2.0.0-java
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +37 -22
- data/bin/rpush +13 -4
- data/lib/generators/rpush_generator.rb +2 -0
- data/lib/generators/templates/add_adm.rb +5 -5
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
- data/lib/generators/templates/add_app_to_rapns.rb +2 -2
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
- data/lib/generators/templates/add_gcm.rb +32 -32
- data/lib/generators/templates/add_rpush.rb +67 -67
- data/lib/generators/templates/add_wpns.rb +2 -2
- data/lib/generators/templates/create_rapns_apps.rb +5 -5
- data/lib/generators/templates/create_rapns_feedback.rb +2 -2
- data/lib/generators/templates/create_rapns_notifications.rb +15 -15
- data/lib/generators/templates/rpush.rb +28 -7
- data/lib/generators/templates/rpush_2_0_0_updates.rb +42 -0
- data/lib/rpush/client/active_model/adm/app.rb +23 -0
- data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
- data/lib/rpush/client/active_model/adm/notification.rb +28 -0
- data/lib/rpush/client/active_model/apns/app.rb +37 -0
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
- data/lib/rpush/client/active_model/apns/notification.rb +90 -0
- data/lib/rpush/client/active_model/gcm/app.rb +19 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
- data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
- data/lib/rpush/client/active_model/notification.rb +26 -0
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
- data/lib/rpush/client/active_model/wpns/app.rb +13 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
- data/lib/rpush/client/active_model.rb +21 -0
- data/lib/rpush/client/active_record/adm/app.rb +11 -0
- data/lib/rpush/client/active_record/adm/notification.rb +11 -0
- data/lib/rpush/client/active_record/apns/app.rb +11 -0
- data/lib/rpush/client/active_record/apns/feedback.rb +22 -0
- data/lib/rpush/client/active_record/apns/notification.rb +46 -0
- data/lib/rpush/client/active_record/app.rb +17 -0
- data/lib/rpush/client/active_record/gcm/app.rb +11 -0
- data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
- data/lib/rpush/client/active_record/notification.rb +38 -0
- data/lib/rpush/client/active_record/wpns/app.rb +11 -0
- data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
- data/lib/rpush/client/active_record.rb +19 -0
- data/lib/rpush/client/redis/adm/app.rb +14 -0
- data/lib/rpush/client/redis/adm/notification.rb +11 -0
- data/lib/rpush/client/redis/apns/app.rb +11 -0
- data/lib/rpush/client/redis/apns/feedback.rb +20 -0
- data/lib/rpush/client/redis/apns/notification.rb +11 -0
- data/lib/rpush/client/redis/app.rb +24 -0
- data/lib/rpush/client/redis/gcm/app.rb +11 -0
- data/lib/rpush/client/redis/gcm/notification.rb +11 -0
- data/lib/rpush/client/redis/notification.rb +68 -0
- data/lib/rpush/client/redis/wpns/app.rb +11 -0
- data/lib/rpush/client/redis/wpns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +35 -0
- data/lib/rpush/configuration.rb +27 -6
- data/lib/rpush/daemon/adm/delivery.rb +56 -55
- data/lib/rpush/daemon/apns/delivery.rb +20 -44
- data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
- data/lib/rpush/daemon/apns.rb +6 -5
- data/lib/rpush/daemon/app_runner.rb +103 -99
- data/lib/rpush/daemon/batch.rb +54 -40
- data/lib/rpush/daemon/delivery.rb +13 -3
- data/lib/rpush/daemon/delivery_error.rb +10 -2
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +114 -0
- data/lib/rpush/daemon/dispatcher/http.rb +3 -3
- data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
- data/lib/rpush/daemon/dispatcher_loop.rb +37 -23
- data/lib/rpush/daemon/errors.rb +18 -0
- data/lib/rpush/daemon/feeder.rb +28 -39
- data/lib/rpush/daemon/gcm/delivery.rb +19 -20
- data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
- data/lib/rpush/daemon/loggable.rb +2 -4
- data/lib/rpush/daemon/proc_title.rb +16 -0
- data/lib/rpush/daemon/queue_payload.rb +12 -0
- data/lib/rpush/daemon/reflectable.rb +3 -5
- data/lib/rpush/daemon/retry_header_parser.rb +6 -6
- data/lib/rpush/daemon/retryable_error.rb +2 -0
- data/lib/rpush/daemon/ring_buffer.rb +16 -0
- data/lib/rpush/daemon/service_config_methods.rb +23 -7
- data/lib/rpush/daemon/signal_handler.rb +56 -0
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +21 -17
- data/lib/rpush/daemon/store/active_record.rb +71 -38
- data/lib/rpush/daemon/store/interface.rb +19 -0
- data/lib/rpush/daemon/store/redis.rb +149 -0
- data/lib/rpush/daemon/string_helpers.rb +15 -0
- data/lib/rpush/daemon/synchronizer.rb +60 -0
- data/lib/rpush/daemon/tcp_connection.rb +6 -11
- data/lib/rpush/daemon/wpns/delivery.rb +21 -30
- data/lib/rpush/daemon.rb +40 -60
- data/lib/rpush/deprecatable.rb +4 -3
- data/lib/rpush/deprecation.rb +7 -10
- data/lib/rpush/embed.rb +8 -3
- data/lib/rpush/logger.rb +11 -15
- data/lib/rpush/push.rb +1 -2
- data/lib/rpush/reflection.rb +8 -12
- data/lib/rpush/version.rb +1 -1
- data/lib/rpush.rb +5 -29
- data/lib/tasks/quality.rake +35 -0
- data/lib/tasks/test.rake +1 -5
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +3 -6
- data/spec/functional/apns_spec.rb +117 -24
- data/spec/functional/embed_spec.rb +20 -20
- data/spec/functional/gcm_spec.rb +4 -7
- data/spec/functional/new_app_spec.rb +59 -0
- data/spec/functional/retry_spec.rb +46 -0
- data/spec/functional/synchronization_spec.rb +68 -0
- data/spec/functional/wpns_spec.rb +3 -6
- data/spec/functional_spec_helper.rb +26 -0
- data/spec/integration/rpush_spec.rb +13 -0
- data/spec/integration/support/gcm_success_response.json +1 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/active_record_setup.rb +48 -0
- data/{config → spec/support/config}/database.yml +0 -0
- data/spec/support/install.sh +43 -7
- data/spec/support/simplecov_helper.rb +9 -5
- data/spec/support/simplecov_quality_formatter.rb +10 -6
- data/spec/unit/apns_feedback_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
- data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
- data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
- data/spec/unit/client/active_record/app_spec.rb +30 -0
- data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
- data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/notification_spec.rb +21 -0
- data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
- data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
- data/spec/unit/configuration_spec.rb +12 -5
- data/spec/unit/daemon/adm/delivery_spec.rb +66 -55
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
- data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +22 -17
- data/spec/unit/daemon/app_runner_spec.rb +78 -186
- data/spec/unit/daemon/batch_spec.rb +52 -115
- data/spec/unit/daemon/delivery_spec.rb +15 -1
- data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
- data/spec/unit/daemon/dispatcher_loop_spec.rb +6 -24
- data/spec/unit/daemon/feeder_spec.rb +38 -39
- data/spec/unit/daemon/gcm/delivery_spec.rb +122 -101
- data/spec/unit/daemon/reflectable_spec.rb +2 -2
- data/spec/unit/daemon/retryable_error_spec.rb +1 -1
- data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
- data/spec/unit/daemon/signal_handler_spec.rb +95 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +48 -27
- data/spec/unit/daemon/store/active_record_spec.rb +38 -47
- data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
- data/spec/unit/daemon/wpns/delivery_spec.rb +58 -50
- data/spec/unit/daemon_spec.rb +48 -82
- data/spec/unit/embed_spec.rb +6 -4
- data/spec/unit/logger_spec.rb +35 -43
- data/spec/unit/notification_shared.rb +9 -79
- data/spec/unit/push_spec.rb +6 -10
- data/spec/unit/reflection_spec.rb +25 -25
- data/spec/unit/rpush_spec.rb +1 -2
- data/spec/unit_spec_helper.rb +33 -88
- metadata +126 -76
- data/lib/rpush/TODO +0 -3
- data/lib/rpush/adm/app.rb +0 -15
- data/lib/rpush/adm/data_validator.rb +0 -11
- data/lib/rpush/adm/notification.rb +0 -29
- data/lib/rpush/apns/app.rb +0 -29
- data/lib/rpush/apns/binary_notification_validator.rb +0 -12
- data/lib/rpush/apns/device_token_format_validator.rb +0 -12
- data/lib/rpush/apns/feedback.rb +0 -16
- data/lib/rpush/apns/notification.rb +0 -84
- data/lib/rpush/app.rb +0 -18
- data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
- data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
- data/lib/rpush/daemon/dispatcher_loop_collection.rb +0 -33
- data/lib/rpush/daemon/too_many_requests_error.rb +0 -20
- data/lib/rpush/gcm/app.rb +0 -11
- data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
- data/lib/rpush/gcm/notification.rb +0 -30
- data/lib/rpush/notification.rb +0 -69
- data/lib/rpush/notifier.rb +0 -52
- data/lib/rpush/payload_data_size_validator.rb +0 -10
- data/lib/rpush/railtie.rb +0 -11
- data/lib/rpush/registration_ids_count_validator.rb +0 -10
- data/lib/rpush/wpns/app.rb +0 -9
- data/lib/rpush/wpns/notification.rb +0 -26
- data/lib/tasks/cane.rake +0 -18
- data/lib/tasks/rpush.rake +0 -16
- 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 -208
- data/spec/unit/app_spec.rb +0 -30
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
- data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +0 -37
- data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
- data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
- data/spec/unit/gcm/app_spec.rb +0 -4
- data/spec/unit/notification_spec.rb +0 -15
- data/spec/unit/notifier_spec.rb +0 -49
- data/spec/unit/wpns/app_spec.rb +0 -4
- data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -1,44 +1,51 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Rpush::Daemon::Gcm::Delivery do
|
4
|
-
let(:app) { Rpush::Gcm::App.
|
5
|
-
let(:notification) { Rpush::Gcm::Notification.create!(:
|
6
|
-
let(:logger) { double(:
|
7
|
-
let(:response) { double(:
|
8
|
-
let(:http) { double(:
|
4
|
+
let(:app) { Rpush::Gcm::App.create!(name: 'MyApp', auth_key: 'abc123') }
|
5
|
+
let(:notification) { Rpush::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
9
|
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
10
|
-
let(:batch) { double(:
|
10
|
+
let(:batch) { double(mark_failed: nil, mark_delivered: nil, mark_retryable: nil, notification_processed: nil) }
|
11
11
|
let(:delivery) { Rpush::Daemon::Gcm::Delivery.new(app, http, notification, batch) }
|
12
|
-
let(:store) { double(:
|
12
|
+
let(:store) { double(create_gcm_notification: double(id: 2)) }
|
13
13
|
|
14
14
|
def perform
|
15
15
|
delivery.perform
|
16
16
|
end
|
17
17
|
|
18
|
+
def perform_with_rescue
|
19
|
+
expect { perform }.to raise_error
|
20
|
+
end
|
21
|
+
|
18
22
|
before do
|
19
|
-
delivery.stub(:
|
20
|
-
Rpush::Daemon.stub(:
|
21
|
-
Time.stub(:
|
22
|
-
Rpush.stub(:
|
23
|
+
delivery.stub(reflect: nil)
|
24
|
+
Rpush::Daemon.stub(store: store)
|
25
|
+
Time.stub(now: now)
|
26
|
+
Rpush.stub(logger: logger)
|
23
27
|
end
|
24
28
|
|
25
29
|
shared_examples_for 'a notification with some delivery failures' do
|
26
30
|
let(:new_notification) { Rpush::Gcm::Notification.where('id != ?', notification.id).first }
|
27
31
|
|
28
|
-
before { response.stub(:
|
32
|
+
before { response.stub(body: JSON.dump(body)) }
|
29
33
|
|
30
34
|
it 'marks the original notification as failed' do
|
31
|
-
|
32
|
-
|
35
|
+
# error = Rpush::DeliveryError.new(nil, notification.id, error_description)
|
36
|
+
delivery.should_receive(:mark_failed) do |error|
|
37
|
+
error.to_s.should =~ error_description
|
38
|
+
end
|
39
|
+
perform_with_rescue
|
33
40
|
end
|
34
41
|
|
35
42
|
it 'creates a new notification for the unavailable devices' do
|
36
|
-
notification.update_attributes(:
|
37
|
-
response.stub(:
|
43
|
+
notification.update_attributes(registration_ids: %w(id_0 id_1 id_2), data: { 'one' => 1 }, collapse_key: 'thing', delay_while_idle: true)
|
44
|
+
response.stub(header: { 'retry-after' => 10 })
|
38
45
|
attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
|
39
46
|
store.should_receive(:create_gcm_notification).with(attrs, notification.data,
|
40
|
-
|
41
|
-
|
47
|
+
%w(id_0 id_2), now + 10.seconds, notification.app)
|
48
|
+
perform_with_rescue
|
42
49
|
end
|
43
50
|
|
44
51
|
it 'raises a DeliveryError' do
|
@@ -48,7 +55,7 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
48
55
|
|
49
56
|
describe 'a 200 response' do
|
50
57
|
before do
|
51
|
-
response.stub(:
|
58
|
+
response.stub(code: 200)
|
52
59
|
end
|
53
60
|
|
54
61
|
it 'reflects on any IDs which successfully received the notification' do
|
@@ -61,11 +68,11 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
61
68
|
]
|
62
69
|
}
|
63
70
|
|
64
|
-
response.stub(:
|
65
|
-
notification.stub(:
|
71
|
+
response.stub(body: JSON.dump(body))
|
72
|
+
notification.stub(registration_ids: %w(1 2))
|
66
73
|
delivery.should_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '1')
|
67
74
|
delivery.should_not_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '2')
|
68
|
-
|
75
|
+
perform_with_rescue
|
69
76
|
end
|
70
77
|
|
71
78
|
it 'reflects on any IDs which failed to receive the notification' do
|
@@ -78,11 +85,11 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
78
85
|
]
|
79
86
|
}
|
80
87
|
|
81
|
-
response.stub(:
|
82
|
-
notification.stub(:
|
88
|
+
response.stub(body: JSON.dump(body))
|
89
|
+
notification.stub(registration_ids: %w(1 2))
|
83
90
|
delivery.should_receive(:reflect).with(:gcm_failed_to_recipient, notification, 'Err', '1')
|
84
91
|
delivery.should_not_receive(:reflect).with(:gcm_failed_to_recipient, notification, anything, '2')
|
85
|
-
|
92
|
+
perform_with_rescue
|
86
93
|
end
|
87
94
|
|
88
95
|
it 'reflects on canonical IDs' do
|
@@ -93,40 +100,43 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
93
100
|
'results' => [
|
94
101
|
{ 'message_id' => '1:000' },
|
95
102
|
{ 'message_id' => '1:000', 'registration_id' => 'canonical123' },
|
96
|
-
{ 'message_id' => '1:000' }
|
97
|
-
]}
|
103
|
+
{ 'message_id' => '1:000' }
|
104
|
+
] }
|
98
105
|
|
99
|
-
response.stub(:
|
100
|
-
notification.stub(:
|
106
|
+
response.stub(body: JSON.dump(body))
|
107
|
+
notification.stub(registration_ids: %w(1 2 3))
|
101
108
|
delivery.should_receive(:reflect).with(:gcm_canonical_id, '2', 'canonical123')
|
102
109
|
perform
|
103
110
|
end
|
104
111
|
|
105
112
|
it 'reflects on invalid IDs' do
|
106
113
|
body = {
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
114
|
+
'failure' => 1,
|
115
|
+
'success' => 2,
|
116
|
+
'canonical_ids' => 0,
|
117
|
+
'results' => [
|
118
|
+
{ 'message_id' => '1:000' },
|
119
|
+
{ 'error' => 'NotRegistered' },
|
120
|
+
{ 'message_id' => '1:000' }
|
121
|
+
]
|
122
|
+
}
|
115
123
|
|
116
|
-
response.stub(:
|
117
|
-
notification.stub(:
|
124
|
+
response.stub(body: JSON.dump(body))
|
125
|
+
notification.stub(registration_ids: %w(1 2 3))
|
118
126
|
delivery.should_receive(:reflect).with(:gcm_invalid_registration_id, app, 'NotRegistered', '2')
|
119
|
-
|
127
|
+
perform_with_rescue
|
120
128
|
end
|
121
129
|
|
122
130
|
describe 'when delivered successfully to all devices' do
|
123
|
-
let(:body)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
131
|
+
let(:body) do
|
132
|
+
{
|
133
|
+
'failure' => 0,
|
134
|
+
'success' => 1,
|
135
|
+
'results' => [{ 'message_id' => '1:000' }]
|
136
|
+
}
|
137
|
+
end
|
128
138
|
|
129
|
-
before { response.stub(:
|
139
|
+
before { response.stub(body: JSON.dump(body)) }
|
130
140
|
|
131
141
|
it 'marks the notification as delivered' do
|
132
142
|
delivery.should_receive(:mark_delivered)
|
@@ -141,20 +151,21 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
141
151
|
|
142
152
|
it 'marks a notification as failed if any ids are invalid' do
|
143
153
|
body = {
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
154
|
+
'failure' => 1,
|
155
|
+
'success' => 2,
|
156
|
+
'canonical_ids' => 0,
|
157
|
+
'results' => [
|
158
|
+
{ 'message_id' => '1:000' },
|
159
|
+
{ 'error' => 'NotRegistered' },
|
160
|
+
{ 'message_id' => '1:000' }
|
161
|
+
]
|
162
|
+
}
|
152
163
|
|
153
|
-
response.stub(:
|
164
|
+
response.stub(body: JSON.dump(body))
|
154
165
|
delivery.should_receive(:mark_failed)
|
155
166
|
delivery.should_not_receive(:mark_retryable)
|
156
167
|
store.should_not_receive(:create_gcm_notification)
|
157
|
-
|
168
|
+
perform_with_rescue
|
158
169
|
end
|
159
170
|
|
160
171
|
it 'marks a notification as failed if any deliveries failed that cannot be retried' do
|
@@ -164,28 +175,32 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
164
175
|
'results' => [
|
165
176
|
{ 'message_id' => '1:000' },
|
166
177
|
{ 'error' => 'InvalidDataKey' }
|
167
|
-
]}
|
168
|
-
response.stub(:
|
169
|
-
|
170
|
-
|
178
|
+
] }
|
179
|
+
response.stub(body: JSON.dump(body))
|
180
|
+
error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients. Errors: InvalidDataKey.')
|
181
|
+
delivery.should_receive(:mark_failed).with(error)
|
182
|
+
perform_with_rescue
|
171
183
|
end
|
172
184
|
|
173
185
|
describe 'all deliveries failed with Unavailable or InternalServerError' do
|
174
|
-
let(:body)
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
186
|
+
let(:body) do
|
187
|
+
{
|
188
|
+
'failure' => 2,
|
189
|
+
'success' => 0,
|
190
|
+
'results' => [
|
191
|
+
{ 'error' => 'Unavailable' },
|
192
|
+
{ 'error' => 'Unavailable' }
|
193
|
+
]
|
194
|
+
}
|
195
|
+
end
|
181
196
|
|
182
197
|
before do
|
183
|
-
response.stub(:
|
184
|
-
notification.stub(:
|
198
|
+
response.stub(body: JSON.dump(body))
|
199
|
+
notification.stub(registration_ids: %w(1 2))
|
185
200
|
end
|
186
201
|
|
187
202
|
it 'retries the notification respecting the Retry-After header' do
|
188
|
-
response.stub(:
|
203
|
+
response.stub(header: { 'retry-after' => 10 })
|
189
204
|
delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
190
205
|
perform
|
191
206
|
end
|
@@ -209,34 +224,38 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
209
224
|
end
|
210
225
|
|
211
226
|
describe 'all deliveries failed with some as Unavailable or InternalServerError' do
|
212
|
-
let(:body)
|
213
|
-
'failure' => 3,
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
227
|
+
let(:body) do
|
228
|
+
{ 'failure' => 3,
|
229
|
+
'success' => 0,
|
230
|
+
'results' => [
|
231
|
+
{ 'error' => 'Unavailable' },
|
232
|
+
{ 'error' => 'InvalidDataKey' },
|
233
|
+
{ 'error' => 'Unavailable' }
|
234
|
+
]
|
235
|
+
}
|
236
|
+
end
|
220
237
|
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]+\./ }
|
221
238
|
it_should_behave_like 'a notification with some delivery failures'
|
222
239
|
end
|
223
240
|
|
224
241
|
describe 'some deliveries failed with Unavailable or InternalServerError' do
|
225
|
-
let(:body)
|
226
|
-
'failure' => 2,
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
242
|
+
let(:body) do
|
243
|
+
{ 'failure' => 2,
|
244
|
+
'success' => 1,
|
245
|
+
'results' => [
|
246
|
+
{ 'error' => 'Unavailable' },
|
247
|
+
{ 'message_id' => '1:000' },
|
248
|
+
{ 'error' => 'InternalServerError' }
|
249
|
+
]
|
250
|
+
}
|
251
|
+
end
|
233
252
|
let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 2. Errors: Unavailable, InternalServerError. 0, 2 will be retried as notification")} [\d]+\./ }
|
234
253
|
it_should_behave_like 'a notification with some delivery failures'
|
235
254
|
end
|
236
255
|
end
|
237
256
|
|
238
257
|
describe 'a 503 response' do
|
239
|
-
before { response.stub(:
|
258
|
+
before { response.stub(code: 503) }
|
240
259
|
|
241
260
|
it 'logs a warning that the notification will be retried.' do
|
242
261
|
notification.retries = 1
|
@@ -246,19 +265,19 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
246
265
|
end
|
247
266
|
|
248
267
|
it 'respects an integer Retry-After header' do
|
249
|
-
response.stub(:
|
268
|
+
response.stub(header: { 'retry-after' => 10 })
|
250
269
|
delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
251
270
|
perform
|
252
271
|
end
|
253
272
|
|
254
273
|
it 'respects a HTTP-date Retry-After header' do
|
255
|
-
response.stub(:
|
274
|
+
response.stub(header: { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
|
256
275
|
delivery.should_receive(:mark_retryable).with(notification, Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
|
257
276
|
perform
|
258
277
|
end
|
259
278
|
|
260
279
|
it 'defaults to exponential back-off if the Retry-After header is not present' do
|
261
|
-
delivery.should_receive(:mark_retryable).with(notification, now + 2
|
280
|
+
delivery.should_receive(:mark_retryable).with(notification, now + 2**1)
|
262
281
|
perform
|
263
282
|
end
|
264
283
|
end
|
@@ -266,24 +285,24 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
266
285
|
describe 'a 500 response' do
|
267
286
|
before do
|
268
287
|
notification.update_attribute(:retries, 2)
|
269
|
-
response.stub(:
|
288
|
+
response.stub(code: 500)
|
270
289
|
end
|
271
290
|
|
272
291
|
it 'logs a warning that the notification has been re-queued.' do
|
273
292
|
notification.retries = 3
|
274
|
-
notification.deliver_after = now + 2
|
275
|
-
Rpush.logger.should_receive(:warn).with("[MyApp] GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2
|
293
|
+
notification.deliver_after = now + 2**3
|
294
|
+
Rpush.logger.should_receive(:warn).with("[MyApp] 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).")
|
276
295
|
perform
|
277
296
|
end
|
278
297
|
|
279
298
|
it 'retries the notification in accordance with the exponential back-off strategy.' do
|
280
|
-
delivery.should_receive(:mark_retryable).with(notification, now + 2
|
299
|
+
delivery.should_receive(:mark_retryable).with(notification, now + 2**3)
|
281
300
|
perform
|
282
301
|
end
|
283
302
|
end
|
284
303
|
|
285
304
|
describe 'a 401 response' do
|
286
|
-
before { response.stub(:
|
305
|
+
before { response.stub(code: 401) }
|
287
306
|
|
288
307
|
it 'raises an error' do
|
289
308
|
expect { perform }.to raise_error(Rpush::DeliveryError)
|
@@ -291,20 +310,22 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
291
310
|
end
|
292
311
|
|
293
312
|
describe 'a 400 response' do
|
294
|
-
before { response.stub(:
|
313
|
+
before { response.stub(code: 400) }
|
295
314
|
|
296
315
|
it 'marks the notification as failed' do
|
297
|
-
|
298
|
-
|
316
|
+
error = Rpush::DeliveryError.new(400, notification.id, 'GCM failed to parse the JSON request. Possibly an Rpush bug, please open an issue.')
|
317
|
+
delivery.should_receive(:mark_failed).with(error)
|
318
|
+
perform_with_rescue
|
299
319
|
end
|
300
320
|
end
|
301
321
|
|
302
322
|
describe 'an un-handled response' do
|
303
|
-
before { response.stub(:
|
323
|
+
before { response.stub(code: 418) }
|
304
324
|
|
305
325
|
it 'marks the notification as failed' do
|
306
|
-
|
307
|
-
|
326
|
+
error = Rpush::DeliveryError.new(418, notification.id, "I'm a Teapot")
|
327
|
+
delivery.should_receive(:mark_failed).with(error)
|
328
|
+
perform_with_rescue
|
308
329
|
end
|
309
330
|
end
|
310
331
|
end
|
@@ -5,12 +5,12 @@ describe Rpush::Daemon::Reflectable do
|
|
5
5
|
include Rpush::Daemon::Reflectable
|
6
6
|
end
|
7
7
|
|
8
|
-
let(:logger) { double(:
|
8
|
+
let(:logger) { double(error: nil) }
|
9
9
|
let(:test_reflectable) { TestReflectable.new }
|
10
10
|
|
11
11
|
before do
|
12
12
|
Rpush.reflections.stub(:__dispatch)
|
13
|
-
Rpush.stub(:
|
13
|
+
Rpush.stub(logger: logger)
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'dispatches the given reflection' do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "unit_spec_helper"
|
2
2
|
|
3
3
|
describe Rpush::RetryableError do
|
4
|
-
let(:response) { double(:
|
4
|
+
let(:response) { double(code: 401, header: { 'retry-after' => 3600 }) }
|
5
5
|
let(:error) { Rpush::RetryableError.new(401, 12, "Unauthorized", response) }
|
6
6
|
|
7
7
|
it "returns an informative message" do
|
@@ -10,10 +10,13 @@ describe Rpush::Daemon::ServiceConfigMethods do
|
|
10
10
|
ServiceConfigMethodsSpec.delivery_class.should eq ServiceConfigMethodsSpec::Delivery
|
11
11
|
end
|
12
12
|
|
13
|
-
it '
|
14
|
-
loop_class =
|
13
|
+
it 'instantiates loops' do
|
14
|
+
loop_class = Class.new
|
15
|
+
app = double
|
16
|
+
loop_instance = loop_class.new
|
17
|
+
loop_class.should_receive(:new).with(app).and_return(loop_instance)
|
15
18
|
ServiceConfigMethodsSpec.loops loop_class
|
16
|
-
ServiceConfigMethodsSpec.
|
19
|
+
ServiceConfigMethodsSpec.loop_instances(app).should eq [loop_instance]
|
17
20
|
end
|
18
21
|
|
19
22
|
it 'returns a new dispatcher' do
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe Rpush::Daemon::SignalHandler do
|
4
|
+
def signal_handler(sig)
|
5
|
+
Process.kill(sig, Process.pid)
|
6
|
+
sleep 0.1
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_handler_start_stop
|
10
|
+
Rpush::Daemon::SignalHandler.start
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
Rpush::Daemon::SignalHandler.stop
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'shutdown signals' do
|
17
|
+
unless Rpush.jruby? # These tests do not work on JRuby.
|
18
|
+
it "shuts down when signaled signaled SIGINT" do
|
19
|
+
with_handler_start_stop do
|
20
|
+
Rpush::Daemon.should_receive(:shutdown)
|
21
|
+
signal_handler('SIGINT')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "shuts down when signaled signaled SIGTERM" do
|
26
|
+
with_handler_start_stop do
|
27
|
+
Rpush::Daemon.should_receive(:shutdown)
|
28
|
+
signal_handler('SIGTERM')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'config.embedded = true' do
|
35
|
+
before { Rpush.config.embedded = true }
|
36
|
+
|
37
|
+
it 'does not trap signals' do
|
38
|
+
Signal.should_not_receive(:trap)
|
39
|
+
Rpush::Daemon::SignalHandler.start
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'HUP' do
|
44
|
+
before do
|
45
|
+
Rpush::Daemon::Synchronizer.stub(:sync)
|
46
|
+
Rpush::Daemon::Feeder.stub(:wakeup)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'syncs' do
|
50
|
+
with_handler_start_stop do
|
51
|
+
Rpush::Daemon::Synchronizer.should_receive(:sync)
|
52
|
+
signal_handler('HUP')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'wakes up the Feeder' do
|
57
|
+
with_handler_start_stop do
|
58
|
+
Rpush::Daemon::Feeder.should_receive(:wakeup)
|
59
|
+
signal_handler('HUP')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'USR2' do
|
65
|
+
it 'instructs the AppRunner to print debug information' do
|
66
|
+
with_handler_start_stop do
|
67
|
+
Rpush::Daemon::AppRunner.should_receive(:debug)
|
68
|
+
signal_handler('USR2')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'error handing' do
|
74
|
+
let(:error) { StandardError.new('test') }
|
75
|
+
|
76
|
+
before { Rpush.stub(logger: double(error: nil)) }
|
77
|
+
|
78
|
+
it 'logs errors received when handling a signal' do
|
79
|
+
Rpush::Daemon::Synchronizer.stub(:sync).and_raise(error)
|
80
|
+
expect(Rpush.logger).to receive(:error).with(error)
|
81
|
+
with_handler_start_stop do
|
82
|
+
signal_handler('HUP')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'does not interrupt processing of further errors' do
|
87
|
+
Rpush::Daemon::Synchronizer.stub(:sync).and_raise(error)
|
88
|
+
expect(Rpush::Daemon::AppRunner).to receive(:debug)
|
89
|
+
with_handler_start_stop do
|
90
|
+
signal_handler('HUP')
|
91
|
+
signal_handler('USR2')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -16,13 +16,13 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
|
|
16
16
|
def perform
|
17
17
|
with_database_reconnect_and_retry do
|
18
18
|
@calls += 1
|
19
|
-
|
19
|
+
fail @error if @calls <= @max_calls
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
let(:adapter_error_class) do
|
25
|
-
case
|
25
|
+
case SPEC_ADAPTER
|
26
26
|
when 'postgresql'
|
27
27
|
PGError
|
28
28
|
when 'mysql'
|
@@ -38,77 +38,98 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
|
|
38
38
|
when 'sqlite3'
|
39
39
|
SQLite3::Exception
|
40
40
|
else
|
41
|
-
|
41
|
+
fail "Please update #{__FILE__} for adapter #{SPEC_ADAPTER}"
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
44
45
|
let(:error) { adapter_error_class.new("db down!") }
|
45
|
-
let(:
|
46
|
+
let(:timeout) { ActiveRecord::ConnectionTimeoutError.new("db lazy!") }
|
47
|
+
let(:test_doubles) { [TestDouble.new(error, 1), TestDouble.new(timeout, 1)] }
|
46
48
|
|
47
49
|
before do
|
48
|
-
@logger = double("Logger", :
|
50
|
+
@logger = double("Logger", info: nil, error: nil, warn: nil)
|
49
51
|
Rpush.stub(:logger).and_return(@logger)
|
50
52
|
|
51
53
|
ActiveRecord::Base.stub(:clear_all_connections!)
|
52
54
|
ActiveRecord::Base.stub(:establish_connection)
|
53
|
-
|
55
|
+
test_doubles.each { |td| allow(td).to receive(:sleep) }
|
54
56
|
end
|
55
57
|
|
56
58
|
it "should log the error raised" do
|
57
59
|
Rpush.logger.should_receive(:error).with(error)
|
58
|
-
|
60
|
+
test_doubles.each(&:perform)
|
59
61
|
end
|
60
62
|
|
61
63
|
it "should log that the database is being reconnected" do
|
62
64
|
Rpush.logger.should_receive(:warn).with("Lost connection to database, reconnecting...")
|
63
|
-
|
65
|
+
test_doubles.each(&:perform)
|
64
66
|
end
|
65
67
|
|
66
68
|
it "should log the reconnection attempt" do
|
67
69
|
Rpush.logger.should_receive(:warn).with("Attempt 1")
|
68
|
-
|
70
|
+
test_doubles.each(&:perform)
|
69
71
|
end
|
70
72
|
|
71
73
|
it "should clear all connections" do
|
72
74
|
ActiveRecord::Base.should_receive(:clear_all_connections!)
|
73
|
-
|
75
|
+
test_doubles.each(&:perform)
|
74
76
|
end
|
75
77
|
|
76
78
|
it "should establish a new connection" do
|
77
79
|
ActiveRecord::Base.should_receive(:establish_connection)
|
78
|
-
|
80
|
+
test_doubles.each(&:perform)
|
79
81
|
end
|
80
82
|
|
81
83
|
it "should test out the new connection by performing a count" do
|
82
|
-
Rpush::Notification.should_receive(:count)
|
83
|
-
|
84
|
+
Rpush::Client::ActiveRecord::Notification.should_receive(:count).twice
|
85
|
+
test_doubles.each(&:perform)
|
84
86
|
end
|
85
87
|
|
86
88
|
context "when the reconnection attempt is not successful" do
|
87
89
|
before do
|
88
|
-
class << Rpush::Notification
|
90
|
+
class << Rpush::Client::ActiveRecord::Notification
|
89
91
|
def count
|
90
92
|
@count_calls += 1
|
91
93
|
return if @count_calls == 2
|
92
|
-
|
94
|
+
fail @error
|
93
95
|
end
|
94
96
|
end
|
95
|
-
Rpush::Notification.instance_variable_set("@count_calls", 0)
|
96
|
-
Rpush::Notification.instance_variable_set("@error", error)
|
97
|
+
Rpush::Client::ActiveRecord::Notification.instance_variable_set("@count_calls", 0)
|
98
|
+
Rpush::Client::ActiveRecord::Notification.instance_variable_set("@error", error)
|
97
99
|
end
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
describe "error behaviour" do
|
102
|
+
it "should log the 2nd attempt" do
|
103
|
+
Rpush.logger.should_receive(:warn).with("Attempt 2")
|
104
|
+
test_doubles[0].perform
|
105
|
+
end
|
103
106
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
+
it "should log errors raised when the reconnection is not successful" do
|
108
|
+
Rpush.logger.should_receive(:error).with(error)
|
109
|
+
test_doubles[0].perform
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should sleep to avoid thrashing when the database is down" do
|
113
|
+
expect(test_doubles[0]).to receive(:sleep).with(2)
|
114
|
+
test_doubles[0].perform
|
115
|
+
end
|
107
116
|
end
|
108
117
|
|
109
|
-
|
110
|
-
|
111
|
-
|
118
|
+
describe "timeout behaviour" do
|
119
|
+
it "should log the 2nd attempt" do
|
120
|
+
Rpush.logger.should_receive(:warn).with("Attempt 2")
|
121
|
+
test_doubles[1].perform
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should log errors raised when the reconnection is not successful" do
|
125
|
+
Rpush.logger.should_receive(:error).with(error)
|
126
|
+
test_doubles[1].perform
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should sleep to avoid thrashing when the database is down" do
|
130
|
+
expect(test_doubles[1]).to receive(:sleep).with(2)
|
131
|
+
test_doubles[1].perform
|
132
|
+
end
|
112
133
|
end
|
113
134
|
end
|
114
135
|
end
|