rpush 2.3.2 → 2.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +1 -1
- data/lib/generators/rpush_migration_generator.rb +21 -6
- data/lib/generators/templates/rpush.rb +5 -5
- data/lib/generators/templates/rpush_2_0_0_updates.rb +24 -0
- data/lib/rpush/client/active_model/apns/notification.rb +1 -1
- data/lib/rpush/client/mongoid.rb +31 -0
- data/lib/rpush/client/mongoid/adm/app.rb +14 -0
- data/lib/rpush/client/mongoid/adm/notification.rb +11 -0
- data/lib/rpush/client/mongoid/apns/app.rb +11 -0
- data/lib/rpush/client/mongoid/apns/feedback.rb +21 -0
- data/lib/rpush/client/mongoid/apns/notification.rb +15 -0
- data/lib/rpush/client/mongoid/app.rb +23 -0
- data/lib/rpush/client/mongoid/gcm/app.rb +11 -0
- data/lib/rpush/client/mongoid/gcm/notification.rb +11 -0
- data/lib/rpush/client/mongoid/notification.rb +43 -0
- data/lib/rpush/client/mongoid/wpns/app.rb +11 -0
- data/lib/rpush/client/mongoid/wpns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +2 -2
- data/lib/rpush/configuration.rb +48 -29
- data/lib/rpush/daemon/adm/delivery.rb +1 -1
- data/lib/rpush/daemon/apns.rb +1 -1
- data/lib/rpush/daemon/apns/feedback_receiver.rb +2 -3
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +2 -1
- data/lib/rpush/daemon/feeder.rb +4 -7
- data/lib/rpush/daemon/gcm/delivery.rb +1 -1
- data/lib/rpush/daemon/interruptible_sleep.rb +5 -50
- data/lib/rpush/daemon/proc_title.rb +2 -1
- data/lib/rpush/daemon/store/active_record.rb +4 -0
- data/lib/rpush/daemon/store/interface.rb +1 -1
- data/lib/rpush/daemon/store/mongoid.rb +157 -0
- data/lib/rpush/daemon/store/redis.rb +6 -2
- data/lib/rpush/deprecatable.rb +1 -2
- data/lib/rpush/deprecation.rb +6 -0
- data/lib/rpush/embed.rb +5 -0
- data/lib/rpush/logger.rb +5 -8
- data/lib/rpush/push.rb +5 -0
- data/lib/rpush/version.rb +1 -1
- data/lib/tasks/quality.rake +1 -1
- data/lib/tasks/test.rake +9 -4
- data/spec/functional/apns_spec.rb +2 -1
- data/spec/functional_spec_helper.rb +2 -2
- data/spec/spec_helper.rb +18 -7
- data/spec/support/config/mongoid.yml +69 -0
- data/spec/support/mongoid_setup.rb +10 -0
- data/spec/unit/client/active_record/adm/app_spec.rb +1 -1
- data/spec/unit/client/active_record/adm/notification_spec.rb +1 -1
- data/spec/unit/client/active_record/apns/app_spec.rb +1 -1
- data/spec/unit/client/active_record/apns/feedback_spec.rb +1 -1
- data/spec/unit/client/active_record/apns/notification_spec.rb +11 -11
- data/spec/unit/client/active_record/app_spec.rb +1 -1
- data/spec/unit/client/active_record/gcm/notification_spec.rb +1 -1
- data/spec/unit/client/active_record/notification_spec.rb +1 -1
- data/spec/unit/client/active_record/wpns/notification_spec.rb +1 -1
- data/spec/unit/configuration_spec.rb +7 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +5 -5
- data/spec/unit/daemon/feeder_spec.rb +2 -2
- data/spec/unit/daemon/proc_title_spec.rb +11 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +1 -1
- data/spec/unit/daemon/store/active_record_spec.rb +21 -12
- data/spec/unit/daemon/store/mongoid_spec.rb +339 -0
- data/spec/unit/daemon/store/redis_spec.rb +365 -0
- data/spec/unit/embed_spec.rb +4 -2
- data/spec/unit/logger_spec.rb +14 -5
- data/spec/unit/notification_shared.rb +1 -1
- data/spec/unit/push_spec.rb +4 -2
- data/spec/unit_spec_helper.rb +3 -3
- metadata +25 -2
@@ -13,16 +13,34 @@ describe Rpush::Daemon::Store::ActiveRecord do
|
|
13
13
|
allow(Time).to receive_messages(now: time)
|
14
14
|
end
|
15
15
|
|
16
|
-
it '
|
16
|
+
it 'updates an notification' do
|
17
17
|
expect(notification).to receive(:save!)
|
18
18
|
store.update_notification(notification)
|
19
19
|
end
|
20
20
|
|
21
|
-
it '
|
21
|
+
it 'updates an app' do
|
22
22
|
expect(app).to receive(:save!)
|
23
23
|
store.update_app(app)
|
24
24
|
end
|
25
25
|
|
26
|
+
it 'finds an app by ID' do
|
27
|
+
expect(store.app(app.id)).to eq(app)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'finds all apps' do
|
31
|
+
app
|
32
|
+
expect(store.all_apps).to eq([app])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'translates an Integer notification ID' do
|
36
|
+
expect(store.translate_integer_notification_id(notification.id)).to eq(notification.id)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns the pending notification count' do
|
40
|
+
notification
|
41
|
+
expect(store.pending_delivery_count).to eq(1)
|
42
|
+
end
|
43
|
+
|
26
44
|
it 'can release a connection' do
|
27
45
|
expect(ActiveRecord::Base.connection).to receive(:close)
|
28
46
|
store.release_connection
|
@@ -43,7 +61,6 @@ describe Rpush::Daemon::Store::ActiveRecord do
|
|
43
61
|
|
44
62
|
it 'loads notifications in batches' do
|
45
63
|
Rpush.config.batch_size = 5000
|
46
|
-
Rpush.config.push = false
|
47
64
|
relation = double.as_null_object
|
48
65
|
expect(relation).to receive(:limit).with(5000)
|
49
66
|
allow(relation).to receive_messages(to_a: [])
|
@@ -51,14 +68,6 @@ describe Rpush::Daemon::Store::ActiveRecord do
|
|
51
68
|
store.deliverable_notifications(Rpush.config.batch_size)
|
52
69
|
end
|
53
70
|
|
54
|
-
it 'does not load notification in batches if in push mode' do
|
55
|
-
Rpush.config.push = true
|
56
|
-
relation = double.as_null_object
|
57
|
-
expect(relation).not_to receive(:limit)
|
58
|
-
allow(Rpush::Notification).to receive_messages(ready_for_delivery: relation)
|
59
|
-
store.deliverable_notifications(Rpush.config.batch_size)
|
60
|
-
end
|
61
|
-
|
62
71
|
it 'loads an undelivered notification without deliver_after set' do
|
63
72
|
notification.update_attributes!(delivered: false, deliver_after: nil)
|
64
73
|
expect(store.deliverable_notifications(Rpush.config.batch_size)).to eq [notification]
|
@@ -345,4 +354,4 @@ describe Rpush::Daemon::Store::ActiveRecord do
|
|
345
354
|
expect(new_notification.new_record?).to be_falsey
|
346
355
|
end
|
347
356
|
end
|
348
|
-
end
|
357
|
+
end if active_record?
|
@@ -0,0 +1,339 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'rpush/daemon/store/mongoid'
|
3
|
+
|
4
|
+
describe Rpush::Daemon::Store::Mongoid do
|
5
|
+
let(:app) { Rpush::Client::Mongoid::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
|
6
|
+
let(:notification) { Rpush::Client::Mongoid::Apns::Notification.create!(device_token: "a" * 64, app: app) }
|
7
|
+
let(:store) { Rpush::Daemon::Store::Mongoid.new }
|
8
|
+
let(:time) { Time.now.utc }
|
9
|
+
let(:logger) { double(Rpush::Logger, error: nil, internal_logger: nil) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Rpush).to receive_messages(logger: logger)
|
13
|
+
allow(Time).to receive_messages(now: time)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'updates an notification' do
|
17
|
+
expect(notification).to receive(:save!)
|
18
|
+
store.update_notification(notification)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'updates an app' do
|
22
|
+
expect(app).to receive(:save!)
|
23
|
+
store.update_app(app)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'finds an app by ID' do
|
27
|
+
expect(store.app(app.id)).to eq(app)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'finds all apps' do
|
31
|
+
expect(store.all_apps).to eq([app])
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'translates an Integer notification ID' do
|
35
|
+
expect(store.translate_integer_notification_id(notification.integer_id)).to eq(notification.id)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns the pending notification count' do
|
39
|
+
notification
|
40
|
+
expect(store.pending_delivery_count).to eq(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'deliverable_notifications' do
|
44
|
+
it 'loads notifications in batches' do
|
45
|
+
Rpush.config.batch_size = 5000
|
46
|
+
relation = double.as_null_object
|
47
|
+
expect(relation).to receive(:limit).with(5000)
|
48
|
+
allow(relation).to receive_messages(to_a: [])
|
49
|
+
allow(store).to receive_messages(ready_for_delivery: relation)
|
50
|
+
store.deliverable_notifications(Rpush.config.batch_size)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'loads an undelivered notification without deliver_after set' do
|
54
|
+
notification.update_attributes!(delivered: false, deliver_after: nil)
|
55
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to eq [notification]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'loads an notification with a deliver_after time in the past' do
|
59
|
+
notification.update_attributes!(delivered: false, deliver_after: 1.hour.ago)
|
60
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to eq [notification]
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'does not load an notification with a deliver_after time in the future' do
|
64
|
+
notification.update_attributes!(delivered: false, deliver_after: 1.hour.from_now)
|
65
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'does not load a previously delivered notification' do
|
69
|
+
notification.update_attributes!(delivered: true, delivered_at: time)
|
70
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
71
|
+
end
|
72
|
+
|
73
|
+
it "does not enqueue a notification that has previously failed delivery" do
|
74
|
+
notification.update_attributes!(delivered: false, failed: true)
|
75
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'mark_retryable' do
|
80
|
+
it 'increments the retry count' do
|
81
|
+
expect do
|
82
|
+
store.mark_retryable(notification, time)
|
83
|
+
end.to change(notification, :retries).by(1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'sets the deliver after timestamp' do
|
87
|
+
deliver_after = time + 10.seconds
|
88
|
+
expect do
|
89
|
+
store.mark_retryable(notification, deliver_after)
|
90
|
+
end.to change(notification, :deliver_after).to(deliver_after)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'saves the notification without validation' do
|
94
|
+
expect(notification).to receive(:save!).with(validate: false)
|
95
|
+
store.mark_retryable(notification, time)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does not save the notification if persist: false' do
|
99
|
+
expect(notification).not_to receive(:save!)
|
100
|
+
store.mark_retryable(notification, time, persist: false)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'mark_batch_retryable' do
|
105
|
+
let(:deliver_after) { time + 10.seconds }
|
106
|
+
|
107
|
+
it 'sets the attributes on the object for use in reflections' do
|
108
|
+
store.mark_batch_retryable([notification], deliver_after)
|
109
|
+
expect(notification.deliver_after).to eq deliver_after
|
110
|
+
expect(notification.retries).to eq 1
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'increments the retired count' do
|
114
|
+
expect do
|
115
|
+
store.mark_batch_retryable([notification], deliver_after)
|
116
|
+
notification.reload
|
117
|
+
end.to change(notification, :retries).by(1)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'sets the deliver after timestamp' do
|
121
|
+
expect do
|
122
|
+
store.mark_batch_retryable([notification], deliver_after)
|
123
|
+
notification.reload
|
124
|
+
end.to change { notification.deliver_after.try(:utc).to_s }.to(deliver_after.utc.to_s)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'mark_delivered' do
|
129
|
+
it 'marks the notification as delivered' do
|
130
|
+
expect do
|
131
|
+
store.mark_delivered(notification, time)
|
132
|
+
end.to change(notification, :delivered).to(true)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'sets the time the notification was delivered' do
|
136
|
+
expect do
|
137
|
+
store.mark_delivered(notification, time)
|
138
|
+
notification.reload
|
139
|
+
end.to change { notification.delivered_at.try(:utc).to_s }.to(time.to_s)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'saves the notification without validation' do
|
143
|
+
expect(notification).to receive(:save!).with(validate: false)
|
144
|
+
store.mark_delivered(notification, time)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'does not save the notification if persist: false' do
|
148
|
+
expect(notification).not_to receive(:save!)
|
149
|
+
store.mark_delivered(notification, time, persist: false)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'mark_batch_delivered' do
|
154
|
+
it 'sets the attributes on the object for use in reflections' do
|
155
|
+
store.mark_batch_delivered([notification])
|
156
|
+
expect(notification.delivered_at).to eq time
|
157
|
+
expect(notification.delivered).to be_truthy
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'marks the notifications as delivered' do
|
161
|
+
expect do
|
162
|
+
store.mark_batch_delivered([notification])
|
163
|
+
notification.reload
|
164
|
+
end.to change(notification, :delivered).to(true)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'sets the time the notifications were delivered' do
|
168
|
+
expect do
|
169
|
+
store.mark_batch_delivered([notification])
|
170
|
+
notification.reload
|
171
|
+
end.to change { notification.delivered_at.try(:utc).to_s }.to(time.to_s)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'mark_failed' do
|
176
|
+
it 'marks the notification as not delivered' do
|
177
|
+
store.mark_failed(notification, nil, '', time)
|
178
|
+
expect(notification.delivered).to eq(false)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'marks the notification as failed' do
|
182
|
+
expect do
|
183
|
+
store.mark_failed(notification, nil, '', time)
|
184
|
+
notification.reload
|
185
|
+
end.to change(notification, :failed).to(true)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'sets the time the notification delivery failed' do
|
189
|
+
expect do
|
190
|
+
store.mark_failed(notification, nil, '', time)
|
191
|
+
notification.reload
|
192
|
+
end.to change { notification.failed_at.try(:utc).to_s }.to(time.to_s)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'sets the error code' do
|
196
|
+
expect do
|
197
|
+
store.mark_failed(notification, 42, '', time)
|
198
|
+
end.to change(notification, :error_code).to(42)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'sets the error description' do
|
202
|
+
expect do
|
203
|
+
store.mark_failed(notification, 42, 'Weeee', time)
|
204
|
+
end.to change(notification, :error_description).to('Weeee')
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'saves the notification without validation' do
|
208
|
+
expect(notification).to receive(:save!).with(validate: false)
|
209
|
+
store.mark_failed(notification, nil, '', time)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'does not save the notification if persist: false' do
|
213
|
+
expect(notification).not_to receive(:save!)
|
214
|
+
store.mark_failed(notification, nil, '', time, persist: false)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe 'mark_batch_failed' do
|
219
|
+
it 'sets the attributes on the object for use in reflections' do
|
220
|
+
store.mark_batch_failed([notification], 123, 'an error')
|
221
|
+
expect(notification.failed_at).to eq time
|
222
|
+
expect(notification.delivered_at).to be_nil
|
223
|
+
expect(notification.delivered).to eq(false)
|
224
|
+
expect(notification.failed).to be_truthy
|
225
|
+
expect(notification.error_code).to eq 123
|
226
|
+
expect(notification.error_description).to eq 'an error'
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'marks the notification as not delivered' do
|
230
|
+
store.mark_batch_failed([notification], nil, '')
|
231
|
+
notification.reload
|
232
|
+
expect(notification.delivered).to be_falsey
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'marks the notification as failed' do
|
236
|
+
expect do
|
237
|
+
store.mark_batch_failed([notification], nil, '')
|
238
|
+
notification.reload
|
239
|
+
end.to change(notification, :failed).to(true)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'sets the time the notification delivery failed' do
|
243
|
+
expect do
|
244
|
+
store.mark_batch_failed([notification], nil, '')
|
245
|
+
notification.reload
|
246
|
+
end.to change { notification.failed_at.try(:utc).to_s }.to(time.to_s)
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'sets the error code' do
|
250
|
+
expect do
|
251
|
+
store.mark_batch_failed([notification], 42, '')
|
252
|
+
notification.reload
|
253
|
+
end.to change(notification, :error_code).to(42)
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'sets the error description' do
|
257
|
+
expect do
|
258
|
+
store.mark_batch_failed([notification], 42, 'Weeee')
|
259
|
+
notification.reload
|
260
|
+
end.to change(notification, :error_description).to('Weeee')
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe 'create_apns_feedback' do
|
265
|
+
it 'creates the Feedback record' do
|
266
|
+
expect(Rpush::Client::Mongoid::Apns::Feedback).to receive(:create!).with(
|
267
|
+
failed_at: time, device_token: 'ab' * 32, app: app)
|
268
|
+
store.create_apns_feedback(time, 'ab' * 32, app)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe 'create_gcm_notification' do
|
273
|
+
let(:data) { { data: true } }
|
274
|
+
let(:attributes) { { device_token: 'ab' * 32 } }
|
275
|
+
let(:registration_ids) { %w(123 456) }
|
276
|
+
let(:deliver_after) { time + 10.seconds }
|
277
|
+
let(:args) { [attributes, data, registration_ids, deliver_after, app] }
|
278
|
+
|
279
|
+
it 'sets the given attributes' do
|
280
|
+
new_notification = store.create_gcm_notification(*args)
|
281
|
+
expect(new_notification.device_token).to eq 'ab' * 32
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'sets the given data' do
|
285
|
+
new_notification = store.create_gcm_notification(*args)
|
286
|
+
expect(new_notification.data).to eq(data: true)
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'sets the given registration IDs' do
|
290
|
+
new_notification = store.create_gcm_notification(*args)
|
291
|
+
expect(new_notification.registration_ids).to eq registration_ids
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'sets the deliver_after timestamp' do
|
295
|
+
new_notification = store.create_gcm_notification(*args)
|
296
|
+
expect(new_notification.deliver_after.utc.to_s).to eq deliver_after.to_s
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'saves the new notification' do
|
300
|
+
new_notification = store.create_gcm_notification(*args)
|
301
|
+
expect(new_notification.new_record?).to be_falsey
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe 'create_adm_notification' do
|
306
|
+
let(:data) { { data: true } }
|
307
|
+
let(:attributes) { { app_id: app.id, collapse_key: 'ckey', delay_while_idle: true } }
|
308
|
+
let(:registration_ids) { %w(123 456) }
|
309
|
+
let(:deliver_after) { time + 10.seconds }
|
310
|
+
let(:args) { [attributes, data, registration_ids, deliver_after, app] }
|
311
|
+
|
312
|
+
it 'sets the given attributes' do
|
313
|
+
new_notification = store.create_adm_notification(*args)
|
314
|
+
expect(new_notification.app_id).to eq app.id
|
315
|
+
expect(new_notification.collapse_key).to eq 'ckey'
|
316
|
+
expect(new_notification.delay_while_idle).to be_truthy
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'sets the given data' do
|
320
|
+
new_notification = store.create_adm_notification(*args)
|
321
|
+
expect(new_notification.data).to eq(data: true)
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'sets the given registration IDs' do
|
325
|
+
new_notification = store.create_adm_notification(*args)
|
326
|
+
expect(new_notification.registration_ids).to eq registration_ids
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'sets the deliver_after timestamp' do
|
330
|
+
new_notification = store.create_adm_notification(*args)
|
331
|
+
expect(new_notification.deliver_after.utc.to_s).to eq deliver_after.to_s
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'saves the new notification' do
|
335
|
+
new_notification = store.create_adm_notification(*args)
|
336
|
+
expect(new_notification.new_record?).to be_falsey
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end if mongoid?
|
@@ -0,0 +1,365 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'rpush/daemon/store/redis'
|
3
|
+
|
4
|
+
describe Rpush::Daemon::Store::Redis do
|
5
|
+
let(:app) { Rpush::Client::Redis::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
|
6
|
+
let(:notification) { Rpush::Client::Redis::Apns::Notification.create!(device_token: "a" * 64, app: app) }
|
7
|
+
let(:store) { Rpush::Daemon::Store::Redis.new }
|
8
|
+
let(:time) { Time.now.utc }
|
9
|
+
let(:logger) { double(Rpush::Logger, error: nil, internal_logger: nil) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Rpush).to receive_messages(logger: logger)
|
13
|
+
allow(Time).to receive_messages(now: time)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'updates an notification' do
|
17
|
+
expect(notification).to receive(:save!)
|
18
|
+
store.update_notification(notification)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'updates an app' do
|
22
|
+
expect(app).to receive(:save!)
|
23
|
+
store.update_app(app)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'finds an app by ID' do
|
27
|
+
app
|
28
|
+
expect(store.app(app.id)).to eq(app)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'finds all apps' do
|
32
|
+
app
|
33
|
+
expect(store.all_apps).to eq([app])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'translates an Integer notification ID' do
|
37
|
+
expect(store.translate_integer_notification_id(notification.id)).to eq(notification.id)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns the pending notification count' do
|
41
|
+
notification
|
42
|
+
expect(store.pending_delivery_count).to eq(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'deliverable_notifications' do
|
46
|
+
it 'loads notifications in batches' do
|
47
|
+
Rpush.config.batch_size = 100
|
48
|
+
allow(store).to receive_messages(pending_notification_ids: [1, 2, 3, 4])
|
49
|
+
expect(Rpush::Client::Redis::Notification).to receive(:find).exactly(4).times
|
50
|
+
store.deliverable_notifications(Rpush.config.batch_size)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'loads an undelivered notification without deliver_after set' do
|
54
|
+
notification.update_attributes!(delivered: false, deliver_after: nil)
|
55
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to eq [notification]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'loads an notification with a deliver_after time in the past' do
|
59
|
+
notification.update_attributes!(delivered: false, deliver_after: 1.hour.ago)
|
60
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to eq [notification]
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'does not load an notification with a deliver_after time in the future' do
|
64
|
+
notification
|
65
|
+
notification = store.deliverable_notifications(Rpush.config.batch_size).first
|
66
|
+
store.mark_retryable(notification, 1.hour.from_now)
|
67
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'does not load a previously delivered notification' do
|
71
|
+
notification
|
72
|
+
notification = store.deliverable_notifications(Rpush.config.batch_size).first
|
73
|
+
store.mark_delivered(notification, Time.now)
|
74
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
75
|
+
end
|
76
|
+
|
77
|
+
it "does not enqueue a notification that has previously failed delivery" do
|
78
|
+
notification
|
79
|
+
notification = store.deliverable_notifications(Rpush.config.batch_size).first
|
80
|
+
store.mark_failed(notification, 0, "failed", Time.now)
|
81
|
+
expect(store.deliverable_notifications(Rpush.config.batch_size)).to be_empty
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'mark_retryable' do
|
86
|
+
it 'increments the retry count' do
|
87
|
+
expect do
|
88
|
+
store.mark_retryable(notification, time)
|
89
|
+
end.to change(notification, :retries).by(1)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'sets the deliver after timestamp' do
|
93
|
+
deliver_after = time + 10.seconds
|
94
|
+
expect do
|
95
|
+
store.mark_retryable(notification, deliver_after)
|
96
|
+
end.to change(notification, :deliver_after).to(deliver_after)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'saves the notification without validation' do
|
100
|
+
expect(notification).to receive(:save!).with(validate: false)
|
101
|
+
store.mark_retryable(notification, time)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'does not save the notification if persist: false' do
|
105
|
+
expect(notification).not_to receive(:save!)
|
106
|
+
store.mark_retryable(notification, time, persist: false)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'mark_ids_retryable' do
|
111
|
+
let(:deliver_after) { time + 10.seconds }
|
112
|
+
|
113
|
+
it 'sets the deliver after timestamp' do
|
114
|
+
expect do
|
115
|
+
store.mark_ids_retryable([notification.id], deliver_after)
|
116
|
+
notification.reload
|
117
|
+
end.to change { notification.deliver_after.try(:utc).to_s }.to(deliver_after.utc.to_s)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'mark_batch_retryable' do
|
122
|
+
let(:deliver_after) { time + 10.seconds }
|
123
|
+
|
124
|
+
it 'sets the attributes on the object for use in reflections' do
|
125
|
+
store.mark_batch_retryable([notification], deliver_after)
|
126
|
+
expect(notification.deliver_after).to eq deliver_after
|
127
|
+
expect(notification.retries).to eq 1
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'increments the retired count' do
|
131
|
+
expect do
|
132
|
+
store.mark_batch_retryable([notification], deliver_after)
|
133
|
+
notification.reload
|
134
|
+
end.to change(notification, :retries).by(1)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'sets the deliver after timestamp' do
|
138
|
+
expect do
|
139
|
+
store.mark_batch_retryable([notification], deliver_after)
|
140
|
+
notification.reload
|
141
|
+
end.to change { notification.deliver_after.try(:utc).to_s }.to(deliver_after.utc.to_s)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe 'mark_delivered' do
|
146
|
+
it 'marks the notification as delivered' do
|
147
|
+
expect do
|
148
|
+
store.mark_delivered(notification, time)
|
149
|
+
end.to change(notification, :delivered).to(true)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'sets the time the notification was delivered' do
|
153
|
+
expect do
|
154
|
+
store.mark_delivered(notification, time)
|
155
|
+
notification.reload
|
156
|
+
end.to change { notification.delivered_at.try(:utc).to_s }.to(time.to_s)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'saves the notification without validation' do
|
160
|
+
expect(notification).to receive(:save!).with(validate: false)
|
161
|
+
store.mark_delivered(notification, time)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'does not save the notification if persist: false' do
|
165
|
+
expect(notification).not_to receive(:save!)
|
166
|
+
store.mark_delivered(notification, time, persist: false)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe 'mark_batch_delivered' do
|
171
|
+
it 'sets the attributes on the object for use in reflections' do
|
172
|
+
store.mark_batch_delivered([notification])
|
173
|
+
expect(notification.delivered_at).to eq time
|
174
|
+
expect(notification.delivered).to be_truthy
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'marks the notifications as delivered' do
|
178
|
+
expect do
|
179
|
+
store.mark_batch_delivered([notification])
|
180
|
+
notification.reload
|
181
|
+
end.to change(notification, :delivered).to(true)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'sets the time the notifications were delivered' do
|
185
|
+
expect do
|
186
|
+
store.mark_batch_delivered([notification])
|
187
|
+
notification.reload
|
188
|
+
end.to change { notification.delivered_at.try(:utc).to_s }.to(time.to_s)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe 'mark_failed' do
|
193
|
+
it 'marks the notification as not delivered' do
|
194
|
+
store.mark_failed(notification, nil, '', time)
|
195
|
+
expect(notification.delivered).to eq(false)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'marks the notification as failed' do
|
199
|
+
expect do
|
200
|
+
store.mark_failed(notification, nil, '', time)
|
201
|
+
notification.reload
|
202
|
+
end.to change(notification, :failed).to(true)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'sets the time the notification delivery failed' do
|
206
|
+
expect do
|
207
|
+
store.mark_failed(notification, nil, '', time)
|
208
|
+
notification.reload
|
209
|
+
end.to change { notification.failed_at.try(:utc).to_s }.to(time.to_s)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'sets the error code' do
|
213
|
+
expect do
|
214
|
+
store.mark_failed(notification, 42, '', time)
|
215
|
+
end.to change(notification, :error_code).to(42)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'sets the error description' do
|
219
|
+
expect do
|
220
|
+
store.mark_failed(notification, 42, 'Weeee', time)
|
221
|
+
end.to change(notification, :error_description).to('Weeee')
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'saves the notification without validation' do
|
225
|
+
expect(notification).to receive(:save!).with(validate: false)
|
226
|
+
store.mark_failed(notification, nil, '', time)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'does not save the notification if persist: false' do
|
230
|
+
expect(notification).not_to receive(:save!)
|
231
|
+
store.mark_failed(notification, nil, '', time, persist: false)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe 'mark_ids_failed' do
|
236
|
+
it 'marks the notification as failed' do
|
237
|
+
expect do
|
238
|
+
store.mark_ids_failed([notification.id], nil, '', Time.now)
|
239
|
+
notification.reload
|
240
|
+
end.to change(notification, :failed).to(true)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe 'mark_batch_failed' do
|
245
|
+
it 'sets the attributes on the object for use in reflections' do
|
246
|
+
store.mark_batch_failed([notification], 123, 'an error')
|
247
|
+
expect(notification.failed_at).to eq time
|
248
|
+
expect(notification.delivered_at).to be_nil
|
249
|
+
expect(notification.delivered).to eq(false)
|
250
|
+
expect(notification.failed).to be_truthy
|
251
|
+
expect(notification.error_code).to eq 123
|
252
|
+
expect(notification.error_description).to eq 'an error'
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'marks the notification as not delivered' do
|
256
|
+
store.mark_batch_failed([notification], nil, '')
|
257
|
+
notification.reload
|
258
|
+
expect(notification.delivered).to be_falsey
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'marks the notification as failed' do
|
262
|
+
expect do
|
263
|
+
store.mark_batch_failed([notification], nil, '')
|
264
|
+
notification.reload
|
265
|
+
end.to change(notification, :failed).to(true)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'sets the time the notification delivery failed' do
|
269
|
+
expect do
|
270
|
+
store.mark_batch_failed([notification], nil, '')
|
271
|
+
notification.reload
|
272
|
+
end.to change { notification.failed_at.try(:utc).to_s }.to(time.to_s)
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'sets the error code' do
|
276
|
+
expect do
|
277
|
+
store.mark_batch_failed([notification], 42, '')
|
278
|
+
notification.reload
|
279
|
+
end.to change(notification, :error_code).to(42)
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'sets the error description' do
|
283
|
+
expect do
|
284
|
+
store.mark_batch_failed([notification], 42, 'Weeee')
|
285
|
+
notification.reload
|
286
|
+
end.to change(notification, :error_description).to('Weeee')
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe 'create_apns_feedback' do
|
291
|
+
it 'creates the Feedback record' do
|
292
|
+
expect(Rpush::Client::Redis::Apns::Feedback).to receive(:create!).with(
|
293
|
+
failed_at: time, device_token: 'ab' * 32, app_id: app.id)
|
294
|
+
store.create_apns_feedback(time, 'ab' * 32, app)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe 'create_gcm_notification' do
|
299
|
+
let(:data) { { data: true } }
|
300
|
+
let(:attributes) { { device_token: 'ab' * 32 } }
|
301
|
+
let(:registration_ids) { %w(123 456) }
|
302
|
+
let(:deliver_after) { time + 10.seconds }
|
303
|
+
let(:args) { [attributes, data, registration_ids, deliver_after, app] }
|
304
|
+
|
305
|
+
it 'sets the given attributes' do
|
306
|
+
new_notification = store.create_gcm_notification(*args)
|
307
|
+
expect(new_notification.device_token).to eq 'ab' * 32
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'sets the given data' do
|
311
|
+
new_notification = store.create_gcm_notification(*args)
|
312
|
+
expect(new_notification.data).to eq(data: true)
|
313
|
+
end
|
314
|
+
|
315
|
+
it 'sets the given registration IDs' do
|
316
|
+
new_notification = store.create_gcm_notification(*args)
|
317
|
+
expect(new_notification.registration_ids).to eq registration_ids
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'sets the deliver_after timestamp' do
|
321
|
+
new_notification = store.create_gcm_notification(*args)
|
322
|
+
expect(new_notification.deliver_after.utc.to_s).to eq deliver_after.to_s
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'saves the new notification' do
|
326
|
+
new_notification = store.create_gcm_notification(*args)
|
327
|
+
expect(new_notification.new_record?).to be_falsey
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
describe 'create_adm_notification' do
|
332
|
+
let(:data) { { data: true } }
|
333
|
+
let(:attributes) { { app_id: app.id, collapse_key: 'ckey', delay_while_idle: true } }
|
334
|
+
let(:registration_ids) { %w(123 456) }
|
335
|
+
let(:deliver_after) { time + 10.seconds }
|
336
|
+
let(:args) { [attributes, data, registration_ids, deliver_after, app] }
|
337
|
+
|
338
|
+
it 'sets the given attributes' do
|
339
|
+
new_notification = store.create_adm_notification(*args)
|
340
|
+
expect(new_notification.app_id).to eq app.id
|
341
|
+
expect(new_notification.collapse_key).to eq 'ckey'
|
342
|
+
expect(new_notification.delay_while_idle).to be_truthy
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'sets the given data' do
|
346
|
+
new_notification = store.create_adm_notification(*args)
|
347
|
+
expect(new_notification.data).to eq(data: true)
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'sets the given registration IDs' do
|
351
|
+
new_notification = store.create_adm_notification(*args)
|
352
|
+
expect(new_notification.registration_ids).to eq registration_ids
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'sets the deliver_after timestamp' do
|
356
|
+
new_notification = store.create_adm_notification(*args)
|
357
|
+
expect(new_notification.deliver_after.utc.to_s).to eq deliver_after.to_s
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'saves the new notification' do
|
361
|
+
new_notification = store.create_adm_notification(*args)
|
362
|
+
expect(new_notification.new_record?).to be_falsey
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end if redis?
|