rapns 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -5,7 +5,7 @@ module Rapns
|
|
5
5
|
|
6
6
|
def validate(record)
|
7
7
|
if record.registration_ids && record.registration_ids.size > LIMIT
|
8
|
-
record.errors[:base] << "GCM notification
|
8
|
+
record.errors[:base] << "GCM notification number of registration_ids cannot be larger than #{LIMIT}."
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
data/lib/rapns/logger.rb
CHANGED
@@ -6,8 +6,12 @@ module Rapns
|
|
6
6
|
begin
|
7
7
|
log = File.open(File.join(Rails.root, 'log', 'rapns.log'), 'a')
|
8
8
|
log.sync = true
|
9
|
-
|
10
|
-
|
9
|
+
if defined?(ActiveSupport::BufferedLogger)
|
10
|
+
@logger = ActiveSupport::BufferedLogger.new(log, Rails.logger.level)
|
11
|
+
@logger.auto_flushing = Rails.logger.respond_to?(:auto_flushing) ? Rails.logger.auto_flushing : true
|
12
|
+
else
|
13
|
+
@logger = ActiveSupport::Logger.new(log, Rails.logger.level)
|
14
|
+
end
|
11
15
|
rescue Errno::ENOENT, Errno::EPERM => e
|
12
16
|
@logger = nil
|
13
17
|
error(e)
|
data/lib/rapns/push.rb
CHANGED
data/lib/rapns/reflection.rb
CHANGED
data/lib/rapns/version.rb
CHANGED
@@ -8,6 +8,11 @@ describe Rapns, 'apns_feedback' do
|
|
8
8
|
Rapns::Daemon::Apns::FeedbackReceiver.stub(:new => receiver)
|
9
9
|
end
|
10
10
|
|
11
|
+
it 'initializes the store' do
|
12
|
+
Rapns::Daemon.should_receive(:initialize_store)
|
13
|
+
Rapns.apns_feedback
|
14
|
+
end
|
15
|
+
|
11
16
|
it 'checks feedback for each app' do
|
12
17
|
Rapns::Daemon::Apns::FeedbackReceiver.should_receive(:new).with(app, 0).and_return(receiver)
|
13
18
|
receiver.should_receive(:check_for_feedback)
|
@@ -40,7 +40,7 @@ describe Rapns::Configuration do
|
|
40
40
|
|
41
41
|
it 'does not allow foreground to be set to false if the platform is JRuby' do
|
42
42
|
config.foreground = true
|
43
|
-
|
43
|
+
Rapns.stub(:jruby? => true)
|
44
44
|
config.foreground = false
|
45
45
|
config.foreground.should be_true
|
46
46
|
end
|
@@ -7,6 +7,7 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
7
7
|
let(:config) { stub(:check_for_errors => true) }
|
8
8
|
let(:connection) { stub(:select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
|
9
9
|
let(:delivery) { Rapns::Daemon::Apns::Delivery.new(app, connection, notification) }
|
10
|
+
let(:store) { stub(:mark_failed => nil, :mark_delivered => nil) }
|
10
11
|
|
11
12
|
def perform
|
12
13
|
begin
|
@@ -16,6 +17,7 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
16
17
|
end
|
17
18
|
|
18
19
|
before do
|
20
|
+
Rapns::Daemon.stub(:store => store)
|
19
21
|
Rapns.stub(:config => config, :logger => logger)
|
20
22
|
end
|
21
23
|
|
@@ -32,7 +34,7 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
32
34
|
end
|
33
35
|
|
34
36
|
it "marks the notification as delivered" do
|
35
|
-
|
37
|
+
store.should_receive(:mark_delivered).with(notification)
|
36
38
|
perform
|
37
39
|
end
|
38
40
|
|
@@ -41,23 +43,6 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
41
43
|
perform
|
42
44
|
end
|
43
45
|
|
44
|
-
it "sets the time the notification was delivered" do
|
45
|
-
now = Time.now
|
46
|
-
Time.stub(:now).and_return(now)
|
47
|
-
notification.should_receive(:delivered_at=).with(now)
|
48
|
-
perform
|
49
|
-
end
|
50
|
-
|
51
|
-
it "does not trigger validations when saving the notification" do
|
52
|
-
notification.should_receive(:save!).with(:validate => false)
|
53
|
-
perform
|
54
|
-
end
|
55
|
-
|
56
|
-
it "updates notification with the ability to reconnect the database" do
|
57
|
-
delivery.should_receive(:with_database_reconnect_and_retry)
|
58
|
-
perform
|
59
|
-
end
|
60
|
-
|
61
46
|
it 'does not check for errors if check_for_errors config option is false' do
|
62
47
|
config.stub(:check_for_errors => false)
|
63
48
|
delivery.should_not_receive(:check_for_error)
|
@@ -67,23 +52,8 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
67
52
|
describe "when delivery fails" do
|
68
53
|
before { connection.stub(:select => true, :read => [8, 4, 69].pack("ccN")) }
|
69
54
|
|
70
|
-
it "
|
71
|
-
|
72
|
-
perform
|
73
|
-
end
|
74
|
-
|
75
|
-
it "sets the notification as not delivered" do
|
76
|
-
notification.should_receive(:delivered=).with(false)
|
77
|
-
perform
|
78
|
-
end
|
79
|
-
|
80
|
-
it "sets the notification delivered_at timestamp to nil" do
|
81
|
-
notification.should_receive(:delivered_at=).with(nil)
|
82
|
-
perform
|
83
|
-
end
|
84
|
-
|
85
|
-
it "sets the notification as failed" do
|
86
|
-
notification.should_receive(:failed=).with(true)
|
55
|
+
it "marks the notification as failed" do
|
56
|
+
store.should_receive(:mark_failed).with(notification, 4, "Missing payload")
|
87
57
|
perform
|
88
58
|
end
|
89
59
|
|
@@ -92,18 +62,6 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
92
62
|
perform
|
93
63
|
end
|
94
64
|
|
95
|
-
it "sets the notification failed_at timestamp" do
|
96
|
-
now = Time.now
|
97
|
-
Time.stub(:now).and_return(now)
|
98
|
-
notification.should_receive(:failed_at=).with(now)
|
99
|
-
perform
|
100
|
-
end
|
101
|
-
|
102
|
-
it "sets the notification error code" do
|
103
|
-
notification.should_receive(:error_code=).with(4)
|
104
|
-
perform
|
105
|
-
end
|
106
|
-
|
107
65
|
it "logs the delivery error" do
|
108
66
|
# checking for the stubbed error doesn't work in jruby, but checking
|
109
67
|
# for the exception by class does.
|
@@ -115,16 +73,6 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
115
73
|
expect { delivery.perform }.to raise_error(Rapns::DeliveryError)
|
116
74
|
end
|
117
75
|
|
118
|
-
it "sets the notification error description" do
|
119
|
-
notification.should_receive(:error_description=).with("Missing payload")
|
120
|
-
perform
|
121
|
-
end
|
122
|
-
|
123
|
-
it "skips validation when saving the notification" do
|
124
|
-
notification.should_receive(:save!).with(:validate => false)
|
125
|
-
perform
|
126
|
-
end
|
127
|
-
|
128
76
|
it "reads 6 bytes from the socket" do
|
129
77
|
connection.should_receive(:read).with(6).and_return(nil)
|
130
78
|
perform
|
@@ -155,13 +103,8 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
155
103
|
expect { delivery.perform }.to raise_error(Rapns::Apns::DisconnectionError)
|
156
104
|
end
|
157
105
|
|
158
|
-
it '
|
159
|
-
|
160
|
-
perform
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'sets the error description on the notification' do
|
164
|
-
notification.should_receive(:error_description=).with("APNs disconnected without returning an error.")
|
106
|
+
it 'marks the notification as failed' do
|
107
|
+
store.should_receive(:mark_failed).with(notification, nil, "APNs disconnected without returning an error.")
|
165
108
|
perform
|
166
109
|
end
|
167
110
|
end
|
@@ -16,8 +16,8 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
16
16
|
receiver.stub(:interruptible_sleep)
|
17
17
|
Rapns.stub(:logger => logger)
|
18
18
|
Rapns::Daemon::Apns::Connection.stub(:new => connection)
|
19
|
-
Rapns::Apns::Feedback.stub(:create! => feedback)
|
20
19
|
receiver.instance_variable_set("@stop", false)
|
20
|
+
Rapns::Daemon.stub(:store => stub(:create_apns_feedback => feedback))
|
21
21
|
end
|
22
22
|
|
23
23
|
def stub_connection_read_with_tuple
|
@@ -58,8 +58,8 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'creates the feedback' do
|
61
|
+
Rapns::Daemon.store.should_receive(:create_apns_feedback).with(Time.at(1323533325), '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', app)
|
61
62
|
stub_connection_read_with_tuple
|
62
|
-
Rapns::Apns::Feedback.should_receive(:create!).with(:failed_at => Time.at(1323533325), :device_token => '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', :app => app)
|
63
63
|
receiver.check_for_feedback
|
64
64
|
end
|
65
65
|
|
@@ -8,10 +8,10 @@ describe Rapns::Daemon::Feeder do
|
|
8
8
|
let(:logger) { stub }
|
9
9
|
|
10
10
|
before do
|
11
|
-
Rapns.stub(:config => config)
|
11
|
+
Rapns.stub(:config => config,:logger => logger)
|
12
|
+
Rapns::Daemon.stub(:store => stub(:deliverable_notifications => [notification]))
|
12
13
|
Rapns::Daemon::Feeder.stub(:stop? => true)
|
13
|
-
Rapns::Daemon::AppRunner.stub(:idle => [stub(:app => app)])
|
14
|
-
Rapns.stub(:logger => logger)
|
14
|
+
Rapns::Daemon::AppRunner.stub(:enqueue => nil, :idle => [stub(:app => app)])
|
15
15
|
end
|
16
16
|
|
17
17
|
def start
|
@@ -25,8 +25,8 @@ describe Rapns::Daemon::Feeder do
|
|
25
25
|
start
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
29
|
-
Rapns::Daemon
|
28
|
+
it 'loads deliverable notifications' do
|
29
|
+
Rapns::Daemon.store.should_receive(:deliverable_notifications).with([app])
|
30
30
|
start
|
31
31
|
end
|
32
32
|
|
@@ -37,72 +37,20 @@ describe Rapns::Daemon::Feeder do
|
|
37
37
|
start
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'loads notifications in batches' do
|
41
|
-
relation = stub.as_null_object
|
42
|
-
relation.should_receive(:limit).with(5000)
|
43
|
-
Rapns::Notification.stub(:ready_for_delivery => relation)
|
44
|
-
start
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'does not load notification in batches if in push mode' do
|
48
|
-
config.stub(:push => true)
|
49
|
-
relation = stub.as_null_object
|
50
|
-
relation.should_not_receive(:limit)
|
51
|
-
Rapns::Notification.stub(:ready_for_delivery => relation)
|
52
|
-
start
|
53
|
-
end
|
54
|
-
|
55
40
|
it "enqueues the notification" do
|
56
|
-
notification.update_attributes!(:delivered => false)
|
57
41
|
Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
|
58
42
|
start
|
59
43
|
end
|
60
44
|
|
61
45
|
it 'reflects the notification has been enqueued' do
|
62
|
-
notification.update_attributes!(:delivered => false)
|
63
46
|
Rapns::Daemon::AppRunner.stub(:enqueue)
|
64
47
|
Rapns::Daemon::Feeder.should_receive(:reflect).with(:notification_enqueued, notification)
|
65
48
|
start
|
66
49
|
end
|
67
50
|
|
68
|
-
it 'does not enqueue the notification if the app runner is still processing the previous batch' do
|
69
|
-
Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
|
70
|
-
start
|
71
|
-
end
|
72
|
-
|
73
|
-
it "enqueues an undelivered notification without deliver_after set" do
|
74
|
-
notification.update_attributes!(:delivered => false, :deliver_after => nil)
|
75
|
-
Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
|
76
|
-
start
|
77
|
-
end
|
78
|
-
|
79
|
-
it "enqueues a notification with a deliver_after time in the past" do
|
80
|
-
notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
|
81
|
-
Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
|
82
|
-
start
|
83
|
-
end
|
84
|
-
|
85
|
-
it "does not enqueue a notification with a deliver_after time in the future" do
|
86
|
-
notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
|
87
|
-
Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
|
88
|
-
start
|
89
|
-
end
|
90
|
-
|
91
|
-
it "does not enqueue a previously delivered notification" do
|
92
|
-
notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
|
93
|
-
Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
|
94
|
-
start
|
95
|
-
end
|
96
|
-
|
97
|
-
it "does not enqueue a notification that has previously failed delivery" do
|
98
|
-
notification.update_attributes!(:delivered => false, :failed => true)
|
99
|
-
Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
|
100
|
-
start
|
101
|
-
end
|
102
|
-
|
103
51
|
it "logs errors" do
|
104
52
|
e = StandardError.new("bork")
|
105
|
-
Rapns::
|
53
|
+
Rapns::Daemon.store.stub(:deliverable_notifications).and_raise(e)
|
106
54
|
Rapns.logger.should_receive(:error).with(e)
|
107
55
|
start
|
108
56
|
end
|
@@ -2,18 +2,21 @@ require 'unit_spec_helper'
|
|
2
2
|
|
3
3
|
describe Rapns::Daemon::Gcm::Delivery do
|
4
4
|
let(:app) { Rapns::Gcm::App.new(:name => 'MyApp', :auth_key => 'abc123') }
|
5
|
-
let(:notification) { Rapns::Gcm::Notification.create!(:app => app, :registration_ids => ['xyz']) }
|
5
|
+
let(:notification) { Rapns::Gcm::Notification.create!(:app => app, :registration_ids => ['xyz'], :deliver_after => Time.now) }
|
6
6
|
let(:logger) { stub(:error => nil, :info => nil, :warn => nil) }
|
7
7
|
let(:response) { stub(:code => 200, :header => {}) }
|
8
8
|
let(:http) { stub(:shutdown => nil, :request => response)}
|
9
9
|
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
10
10
|
let(:delivery) { Rapns::Daemon::Gcm::Delivery.new(app, http, notification) }
|
11
|
+
let(:store) { stub(:mark_failed => nil, :mark_delivered => nil, :retry_after => nil, :create_gcm_notification => stub(:id => 2)) }
|
11
12
|
|
12
13
|
def perform
|
13
14
|
delivery.perform
|
14
15
|
end
|
15
16
|
|
16
17
|
before do
|
18
|
+
delivery.stub(:reflect => nil)
|
19
|
+
Rapns::Daemon.stub(:store => store)
|
17
20
|
Time.stub(:now => now)
|
18
21
|
Rapns.stub(:logger => logger)
|
19
22
|
end
|
@@ -25,9 +28,8 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
25
28
|
|
26
29
|
it 'marks the notification as delivered if delivered successfully to all devices' do
|
27
30
|
response.stub(:body => JSON.dump({ 'failure' => 0 }))
|
28
|
-
|
29
|
-
|
30
|
-
end.to change(notification, :delivered).to(true)
|
31
|
+
store.should_receive(:mark_delivered).with(notification)
|
32
|
+
perform
|
31
33
|
end
|
32
34
|
|
33
35
|
it 'reflects the notification was delivered' do
|
@@ -51,11 +53,25 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
51
53
|
{ 'error' => 'NotRegistered' }
|
52
54
|
]}
|
53
55
|
response.stub(:body => JSON.dump(body))
|
56
|
+
store.should_receive(:mark_failed).with(notification, nil, "Failed to deliver to all recipients. Errors: NotRegistered.")
|
54
57
|
perform rescue Rapns::DeliveryError
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'reflects on canonical IDs' do
|
61
|
+
body = {
|
62
|
+
'failure' => 0,
|
63
|
+
'success' => 3,
|
64
|
+
'canonical_ids' => 1,
|
65
|
+
'results' => [
|
66
|
+
{ 'message_id' => '1:000' },
|
67
|
+
{ 'message_id' => '1:000', 'registration_id' => 'canonical123' },
|
68
|
+
{ 'message_id' => '1:000' },
|
69
|
+
]}
|
70
|
+
|
71
|
+
response.stub(:body => JSON.dump(body))
|
72
|
+
notification.stub(:registration_ids => ['1', '2', '3'])
|
73
|
+
delivery.should_receive(:reflect).with(:gcm_canonical_id, '2', 'canonical123')
|
74
|
+
perform
|
59
75
|
end
|
60
76
|
|
61
77
|
describe 'all deliveries returned Unavailable or InternalServerError' do
|
@@ -71,28 +87,23 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
71
87
|
|
72
88
|
it 'retries the notification respecting the Retry-After header' do
|
73
89
|
response.stub(:header => { 'retry-after' => 10 })
|
90
|
+
store.should_receive(:retry_after).with(notification, now + 10.seconds)
|
74
91
|
perform
|
75
|
-
notification.reload
|
76
|
-
notification.retries.should == 1
|
77
|
-
notification.deliver_after.should == now + 10.seconds
|
78
92
|
end
|
79
93
|
|
80
94
|
it 'retries the notification using exponential back-off if the Retry-After header is not present' do
|
81
|
-
|
95
|
+
store.should_receive(:retry_after).with(notification, now + 2)
|
82
96
|
perform
|
83
|
-
notification.reload
|
84
|
-
notification.retries.should == 9
|
85
|
-
notification.deliver_after.should == now + 2 ** 9
|
86
97
|
end
|
87
98
|
|
88
99
|
it 'does not mark the notification as failed' do
|
89
|
-
|
90
|
-
|
91
|
-
notification.reload
|
92
|
-
end.to_not change(notification, :failed).to(true)
|
100
|
+
store.should_not_receive(:mark_failed)
|
101
|
+
perform
|
93
102
|
end
|
94
103
|
|
95
104
|
it 'logs that the notification will be retried' do
|
105
|
+
notification.retries = 1
|
106
|
+
notification.deliver_after = now + 2
|
96
107
|
Rapns.logger.should_receive(:warn).with("All recipients unavailable. Notification #{notification.id} will be retired after 2012-10-14 00:00:02 (retry 1).")
|
97
108
|
perform
|
98
109
|
end
|
@@ -104,12 +115,8 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
104
115
|
before { response.stub(:body => JSON.dump(body)) }
|
105
116
|
|
106
117
|
it 'marks the original notification as failed' do
|
118
|
+
store.should_receive(:mark_failed).with(notification, nil, error_description)
|
107
119
|
perform rescue Rapns::DeliveryError
|
108
|
-
notification.reload
|
109
|
-
notification.failed.should be_true
|
110
|
-
notification.failed_at = now
|
111
|
-
notification.error_code.should be_nil
|
112
|
-
notification.error_description.should == error_description
|
113
120
|
end
|
114
121
|
|
115
122
|
it 'reflects the notification delivery failed' do
|
@@ -119,17 +126,11 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
119
126
|
|
120
127
|
it 'creates a new notification for the unavailable devices' do
|
121
128
|
notification.update_attributes(:registration_ids => ['id_0', 'id_1', 'id_2'], :data => {'one' => 1}, :collapse_key => 'thing', :delay_while_idle => true)
|
122
|
-
perform rescue Rapns::DeliveryError
|
123
|
-
new_notification.registration_ids.should == ['id_0', 'id_2']
|
124
|
-
new_notification.data.should == {'one' => 1}
|
125
|
-
new_notification.collapse_key.should == 'thing'
|
126
|
-
new_notification.delay_while_idle.should be_true
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'sets the delivery time on the new notification to respect the Retry-After header' do
|
130
129
|
response.stub(:header => { 'retry-after' => 10 })
|
130
|
+
attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
|
131
|
+
store.should_receive(:create_gcm_notification).with(attrs, notification.data,
|
132
|
+
['id_0', 'id_2'], now + 10.seconds, notification.app)
|
131
133
|
perform rescue Rapns::DeliveryError
|
132
|
-
new_notification.deliver_after.should == now + 10.seconds
|
133
134
|
end
|
134
135
|
|
135
136
|
it 'raises a DeliveryError' do
|
@@ -168,28 +169,27 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
168
169
|
before { response.stub(:code => 503) }
|
169
170
|
|
170
171
|
it 'logs a warning that the notification will be retried.' do
|
172
|
+
notification.retries = 1
|
173
|
+
notification.deliver_after = now + 2
|
171
174
|
logger.should_receive(:warn).with("GCM responded with an Service Unavailable Error. Notification #{notification.id} will be retired after 2012-10-14 00:00:02 (retry 1).")
|
172
175
|
perform
|
173
176
|
end
|
174
177
|
|
175
178
|
it 'respects an integer Retry-After header' do
|
176
179
|
response.stub(:header => { 'retry-after' => 10 })
|
177
|
-
|
178
|
-
|
179
|
-
end.to change(notification, :deliver_after).to(now + 10)
|
180
|
+
store.should_receive(:retry_after).with(notification, now + 10.seconds)
|
181
|
+
perform
|
180
182
|
end
|
181
183
|
|
182
184
|
it 'respects a HTTP-date Retry-After header' do
|
183
185
|
response.stub(:header => { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
|
184
|
-
|
185
|
-
|
186
|
-
end.to change(notification, :deliver_after).to(Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
|
186
|
+
store.should_receive(:retry_after).with(notification, Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
|
187
|
+
perform
|
187
188
|
end
|
188
189
|
|
189
190
|
it 'defaults to exponential back-off if the Retry-After header is not present' do
|
190
|
-
|
191
|
-
|
192
|
-
end.to change(notification, :deliver_after).to(now + 2 ** 1)
|
191
|
+
store.should_receive(:retry_after).with(notification, now + 2 ** 1)
|
192
|
+
perform
|
193
193
|
end
|
194
194
|
|
195
195
|
it 'reflects the notification will be retried' do
|
@@ -205,15 +205,15 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
205
205
|
end
|
206
206
|
|
207
207
|
it 'logs a warning that the notification has been re-queued.' do
|
208
|
+
notification.retries = 3
|
209
|
+
notification.deliver_after = now + 2 ** 3
|
208
210
|
Rapns.logger.should_receive(:warn).with("GCM responded with an Internal Error. Notification #{notification.id} will be retired after #{(now + 2 ** 3).strftime("%Y-%m-%d %H:%M:%S")} (retry 3).")
|
209
211
|
perform
|
210
212
|
end
|
211
213
|
|
212
|
-
it '
|
213
|
-
|
214
|
-
|
215
|
-
notification.reload
|
216
|
-
end.to change(notification, :deliver_after).to(now + 2 ** 3)
|
214
|
+
it 'retries the notification in accordance with the exponential back-off strategy.' do
|
215
|
+
store.should_receive(:retry_after).with(notification, now + 2 ** 3)
|
216
|
+
perform
|
217
217
|
end
|
218
218
|
|
219
219
|
it 'reflects the notification will be retried' do
|
@@ -234,12 +234,8 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
234
234
|
before { response.stub(:code => 400) }
|
235
235
|
|
236
236
|
it 'marks the notification as failed' do
|
237
|
+
store.should_receive(:mark_failed).with(notification, 400, 'GCM failed to parse the JSON request. Possibly an rapns bug, please open an issue.')
|
237
238
|
perform rescue Rapns::DeliveryError
|
238
|
-
notification.reload
|
239
|
-
notification.failed.should be_true
|
240
|
-
notification.failed_at.should == now
|
241
|
-
notification.error_code.should == 400
|
242
|
-
notification.error_description.should == 'GCM failed to parse the JSON request. Possibly an rapns bug, please open an issue.'
|
243
239
|
end
|
244
240
|
|
245
241
|
it 'reflects the notification delivery failed' do
|
@@ -252,12 +248,8 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
252
248
|
before { response.stub(:code => 418) }
|
253
249
|
|
254
250
|
it 'marks the notification as failed' do
|
251
|
+
store.should_receive(:mark_failed).with(notification, 418, "I'm a Teapot")
|
255
252
|
perform rescue Rapns::DeliveryError
|
256
|
-
notification.reload
|
257
|
-
notification.failed.should be_true
|
258
|
-
notification.failed_at.should == now
|
259
|
-
notification.error_code.should == 418
|
260
|
-
notification.error_description.should == "I'm a Teapot"
|
261
253
|
end
|
262
254
|
|
263
255
|
it 'reflects the notification delivery failed' do
|