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,23 +1,21 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
require 'unit/notification_shared.rb'
|
3
3
|
|
4
|
-
describe Rpush::Gcm::Notification do
|
4
|
+
describe Rpush::Client::ActiveRecord::Gcm::Notification do
|
5
5
|
it_should_behave_like 'an Notification subclass'
|
6
6
|
|
7
|
-
let(:app) { Rpush::Gcm::App.create!(:
|
8
|
-
let(:notification_class) { Rpush::Gcm::Notification }
|
7
|
+
let(:app) { Rpush::Client::ActiveRecord::Gcm::App.create!(name: 'test', auth_key: 'abc') }
|
8
|
+
let(:notification_class) { Rpush::Client::ActiveRecord::Gcm::Notification }
|
9
9
|
let(:notification) { notification_class.new }
|
10
|
-
let(:data_setter) { 'data=' }
|
11
|
-
let(:data_getter) { 'data' }
|
12
10
|
|
13
11
|
it "has a 'data' payload limit of 4096 bytes" do
|
14
|
-
notification.data = { :
|
12
|
+
notification.data = { key: "a" * 4096 }
|
15
13
|
notification.valid?.should be_false
|
16
14
|
notification.errors[:base].should eq ["Notification payload data cannot be larger than 4096 bytes."]
|
17
15
|
end
|
18
16
|
|
19
17
|
it 'limits the number of registration ids to 1000' do
|
20
|
-
notification.registration_ids = ['a']*(1000+1)
|
18
|
+
notification.registration_ids = ['a'] * (1000 + 1)
|
21
19
|
notification.valid?.should be_false
|
22
20
|
notification.errors[:base].should eq ["Number of registration_ids cannot be larger than 1000."]
|
23
21
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe Rpush::Client::ActiveRecord::Notification do
|
4
|
+
let(:notification) { Rpush::Client::ActiveRecord::Notification.new }
|
5
|
+
|
6
|
+
it 'allows assignment of many registration IDs' do
|
7
|
+
notification.registration_ids = %w(a b)
|
8
|
+
notification.registration_ids.should eq %w(a b)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'allows assignment of a single registration ID' do
|
12
|
+
notification.registration_ids = 'a'
|
13
|
+
notification.registration_ids.should eq ['a']
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'saves its parent App if required' do
|
17
|
+
notification.app = Rpush::Client::ActiveRecord::App.new(name: "aname")
|
18
|
+
expect(notification.app).to be_valid
|
19
|
+
expect(notification).to be_valid
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'unit/notification_shared.rb'
|
3
|
+
|
4
|
+
describe Rpush::Client::ActiveRecord::Wpns::Notification do
|
5
|
+
it_should_behave_like 'an Notification subclass'
|
6
|
+
let(:app) { Rpush::Client::ActiveRecord::Wpns::App.create!(name: 'test', auth_key: 'abc') }
|
7
|
+
let(:notification_class) { Rpush::Client::ActiveRecord::Wpns::Notification }
|
8
|
+
let(:notification) { notification_class.new }
|
9
|
+
|
10
|
+
it "should have an url in the uri parameter" do
|
11
|
+
notification = Rpush::Client::ActiveRecord::Wpns::Notification.new(uri: "somthing")
|
12
|
+
notification.valid?
|
13
|
+
notification.errors[:uri].include?("is invalid").should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be invalid if there's no message" do
|
17
|
+
notification = Rpush::Client::ActiveRecord::Wpns::Notification.new(alert: "")
|
18
|
+
notification.valid?
|
19
|
+
notification.errors[:alert].include?("can't be blank").should be_true
|
20
|
+
end
|
21
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Rpush do
|
4
|
-
let(:config) {
|
4
|
+
let(:config) { Rpush.config }
|
5
5
|
|
6
|
-
before
|
6
|
+
before do
|
7
|
+
Rpush.stub(require: nil)
|
8
|
+
Rpush.stub(config: config)
|
9
|
+
end
|
7
10
|
|
8
|
-
it '
|
11
|
+
it 'yields a configure block' do
|
9
12
|
expect { |b| Rpush.configure(&b) }.to yield_with_args(config)
|
10
13
|
end
|
11
14
|
end
|
@@ -26,9 +29,8 @@ describe Rpush::Configuration do
|
|
26
29
|
end
|
27
30
|
|
28
31
|
it 'sets the pid_file relative if not absolute' do
|
29
|
-
Rails.stub(:root => '/rails')
|
30
32
|
config.pid_file = 'tmp/rpush.pid'
|
31
|
-
config.pid_file.should eq '/
|
33
|
+
config.pid_file.should eq '/tmp/rails_root/tmp/rpush.pid'
|
32
34
|
end
|
33
35
|
|
34
36
|
it 'does not alter an absolute pid_file path' do
|
@@ -42,4 +44,9 @@ describe Rpush::Configuration do
|
|
42
44
|
config.foreground = false
|
43
45
|
config.foreground.should be_true
|
44
46
|
end
|
47
|
+
|
48
|
+
it 'delegate redis_options to Modis' do
|
49
|
+
Rpush.config.redis_options = { hi: :mom }
|
50
|
+
Modis.redis_options.should eq(hi: :mom)
|
51
|
+
end
|
45
52
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Rpush::Daemon::Adm::Delivery do
|
4
|
-
let(:app) { Rpush::Adm::App.
|
5
|
-
let(:notification) { Rpush::Adm::Notification.create!(:
|
6
|
-
let(:logger) { double(:
|
7
|
-
let(:response) { double(:
|
8
|
-
let(:http) { double(:
|
4
|
+
let(:app) { Rpush::Adm::App.create!(name: 'MyApp', client_id: 'CLIENT_ID', client_secret: 'CLIENT_SECRET') }
|
5
|
+
let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: ['xyz'], deliver_after: Time.now, data: { 'message' => 'test' }) }
|
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::Adm::Delivery.new(app, http, notification, batch) }
|
12
|
-
let(:store) { double(:
|
12
|
+
let(:store) { double(create_adm_notification: double(id: 2)) }
|
13
13
|
|
14
14
|
def perform
|
15
15
|
delivery.perform
|
@@ -19,44 +19,45 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
19
19
|
app.access_token = 'ACCESS_TOKEN'
|
20
20
|
app.access_token_expiration = Time.now + 1.month
|
21
21
|
|
22
|
-
delivery.stub(:
|
23
|
-
Rpush::Daemon.stub(:
|
24
|
-
Time.stub(:
|
25
|
-
Rpush.stub(:
|
22
|
+
delivery.stub(reflect: nil)
|
23
|
+
Rpush::Daemon.stub(store: store)
|
24
|
+
Time.stub(now: now)
|
25
|
+
Rpush.stub(logger: logger)
|
26
26
|
end
|
27
27
|
|
28
28
|
describe 'unknown error response' do
|
29
29
|
before do
|
30
|
-
response.stub(:
|
30
|
+
response.stub(code: 408)
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'marks the notification as failed because no successful delivery was made' do
|
34
|
-
response.stub(:
|
35
|
-
|
34
|
+
response.stub(body: JSON.dump('reason' => 'InvalidData'))
|
35
|
+
error = Rpush::DeliveryError.new(408, notification.id, 'Request Timeout')
|
36
|
+
delivery.should_receive(:mark_failed).with(error)
|
36
37
|
expect { perform }.to raise_error(Rpush::DeliveryError)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
describe 'a 200 (Ok) response' do
|
41
42
|
before do
|
42
|
-
response.stub(:
|
43
|
+
response.stub(code: 200)
|
43
44
|
end
|
44
45
|
|
45
46
|
it 'marks the notification as delivered if delivered successfully to all devices' do
|
46
|
-
response.stub(:
|
47
|
+
response.stub(body: JSON.dump('registrationID' => 'xyz'))
|
47
48
|
delivery.should_receive(:mark_delivered)
|
48
49
|
perform
|
49
50
|
end
|
50
51
|
|
51
52
|
it 'logs that the notification was delivered' do
|
52
|
-
response.stub(:
|
53
|
+
response.stub(body: JSON.dump('registrationID' => 'xyz'))
|
53
54
|
logger.should_receive(:info).with("[MyApp] #{notification.id} sent to xyz")
|
54
55
|
perform
|
55
56
|
end
|
56
57
|
|
57
58
|
it 'reflects on canonical IDs' do
|
58
|
-
response.stub(:
|
59
|
-
notification.stub(:
|
59
|
+
response.stub(body: JSON.dump('registrationID' => 'canonical123'))
|
60
|
+
notification.stub(registration_ids: ['1'])
|
60
61
|
delivery.should_receive(:reflect).with(:adm_canonical_id, '1', 'canonical123')
|
61
62
|
perform
|
62
63
|
end
|
@@ -64,31 +65,40 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
64
65
|
|
65
66
|
describe 'a 400 (Bad Request) response' do
|
66
67
|
before do
|
67
|
-
response.stub(:
|
68
|
+
response.stub(code: 400)
|
68
69
|
end
|
69
70
|
|
70
71
|
it 'marks the notification as failed because no successful delivery was made' do
|
71
|
-
response.stub(:
|
72
|
-
|
73
|
-
|
72
|
+
response.stub(body: JSON.dump('reason' => 'InvalidData'))
|
73
|
+
error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients.')
|
74
|
+
delivery.should_receive(:mark_failed).with(error)
|
75
|
+
expect { perform }.to raise_error(error)
|
74
76
|
end
|
75
77
|
|
76
78
|
it 'logs that the notification was not delivered' do
|
77
|
-
response.stub(:
|
79
|
+
response.stub(body: JSON.dump('reason' => 'InvalidRegistrationId'))
|
78
80
|
logger.should_receive(:warn).with("[MyApp] bad_request: xyz (InvalidRegistrationId)")
|
79
|
-
expect { perform }.to raise_error
|
81
|
+
expect { perform }.to raise_error
|
80
82
|
end
|
83
|
+
|
84
|
+
it 'reflects' do
|
85
|
+
response.stub(body: JSON.dump('registrationID' => 'canonical123', 'reason' => 'Unregistered'))
|
86
|
+
notification.stub(registration_ids: ['1'])
|
87
|
+
delivery.should_receive(:reflect).with(:adm_failed_to_recipient, notification, '1', 'Unregistered')
|
88
|
+
expect { perform }.to raise_error
|
89
|
+
end
|
90
|
+
|
81
91
|
end
|
82
92
|
|
83
93
|
describe 'a 401 (Unauthorized) response' do
|
84
|
-
let(:http) { double(:
|
85
|
-
let(:token_response) { double(:
|
94
|
+
let(:http) { double(shutdown: nil) }
|
95
|
+
let(:token_response) { double(code: 200, header: {}, body: JSON.dump('access_token' => 'ACCESS_TOKEN', 'expires_in' => 60)) }
|
86
96
|
|
87
97
|
before do
|
88
|
-
response.stub(:
|
98
|
+
response.stub(code: 401, header: { 'retry-after' => 10 })
|
89
99
|
|
90
100
|
# first request to deliver message that returns unauthorized response
|
91
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
101
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
|
92
102
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
|
93
103
|
end
|
94
104
|
|
@@ -116,7 +126,7 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
116
126
|
end
|
117
127
|
|
118
128
|
it 'should log the error and stop retrying if new access token can\'t be retrieved' do
|
119
|
-
token_response.stub(:
|
129
|
+
token_response.stub(code: 404, body: "test")
|
120
130
|
# request for access token
|
121
131
|
http.should_receive(:request).with(Rpush::Daemon::Adm::Delivery::AMAZON_TOKEN_URI, instance_of(Net::HTTP::Post)).and_return(token_response)
|
122
132
|
|
@@ -130,15 +140,15 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
130
140
|
end
|
131
141
|
|
132
142
|
describe 'a 429 (Too Many Request) response' do
|
133
|
-
let(:http) { double(:
|
134
|
-
let(:notification) { Rpush::Adm::Notification.create!(:
|
135
|
-
let(:
|
143
|
+
let(:http) { double(shutdown: nil) }
|
144
|
+
let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: %w(abc xyz), deliver_after: Time.now, collapse_key: 'sync', data: { 'message' => 'test' }) }
|
145
|
+
let(:rate_limited_response) { double(code: 429, header: { 'retry-after' => 3600 }) }
|
136
146
|
|
137
147
|
it 'should retry the entire notification respecting the Retry-After header if none sent out yet' do
|
138
|
-
response.stub(:
|
148
|
+
response.stub(code: 429, header: { 'retry-after' => 3600 })
|
139
149
|
|
140
150
|
# first request to deliver message that returns too many request response
|
141
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
151
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
|
142
152
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
|
143
153
|
|
144
154
|
delivery.should_receive(:mark_retryable).with(notification, now + 1.hour)
|
@@ -146,36 +156,36 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
146
156
|
end
|
147
157
|
|
148
158
|
it 'should retry the entire notification using exponential backoff' do
|
149
|
-
response.stub(:
|
159
|
+
response.stub(code: 429, header: {})
|
150
160
|
|
151
161
|
# first request to deliver message that returns too many request response
|
152
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
162
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
|
153
163
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
|
154
164
|
|
155
|
-
delivery.should_receive(:mark_retryable).with(notification, Time.now + 2
|
165
|
+
delivery.should_receive(:mark_retryable).with(notification, Time.now + 2**(notification.retries + 1))
|
156
166
|
perform
|
157
167
|
end
|
158
168
|
|
159
169
|
it 'should keep sent reg ids in original notification and create new notification with remaining reg ids for retry' do
|
160
|
-
response.stub(:
|
170
|
+
response.stub(code: 200, body: JSON.dump('registrationID' => 'abc'))
|
161
171
|
|
162
172
|
# first request to deliver message succeeds
|
163
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
173
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'abc'))
|
164
174
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
|
165
175
|
|
166
176
|
# first request to deliver message that returns too many request response
|
167
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
168
|
-
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(
|
177
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'xyz'))
|
178
|
+
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(rate_limited_response)
|
169
179
|
|
170
180
|
store.should_receive(:update_notification).with do |notif|
|
171
181
|
notif.registration_ids.include?('abc').should be_true
|
172
182
|
notif.registration_ids.include?('xyz').should be_false
|
173
183
|
end
|
174
184
|
|
175
|
-
store.should_receive(:create_adm_notification).with do |attrs,
|
176
|
-
attrs.
|
177
|
-
attrs.
|
178
|
-
attrs.
|
185
|
+
store.should_receive(:create_adm_notification).with do |attrs, _notification_data, reg_ids, deliver_after, notification_app|
|
186
|
+
attrs.key?('collapse_key').should be_true
|
187
|
+
attrs.key?('delay_while_idle').should be_true
|
188
|
+
attrs.key?('app_id').should be_true
|
179
189
|
|
180
190
|
reg_ids.should eq ['xyz']
|
181
191
|
deliver_after.should eq now + 1.hour
|
@@ -190,11 +200,12 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
190
200
|
|
191
201
|
describe 'a 500 (Internal Server Error) response' do
|
192
202
|
before do
|
193
|
-
response.stub(:
|
203
|
+
response.stub(code: 500)
|
194
204
|
end
|
195
205
|
|
196
206
|
it 'marks the notification as failed because no successful delivery was made' do
|
197
|
-
|
207
|
+
error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients.')
|
208
|
+
delivery.should_receive(:mark_failed).with(error)
|
198
209
|
expect { perform }.to raise_error(Rpush::DeliveryError)
|
199
210
|
end
|
200
211
|
|
@@ -206,7 +217,7 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
206
217
|
|
207
218
|
describe 'a 503 (Service Unavailable) response' do
|
208
219
|
before do
|
209
|
-
response.stub(:
|
220
|
+
response.stub(code: 503, header: { 'retry-after' => 10 })
|
210
221
|
end
|
211
222
|
|
212
223
|
it 'should retry the notification respecting the Retry-After header' do
|
@@ -216,19 +227,19 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
216
227
|
end
|
217
228
|
|
218
229
|
describe 'some registration ids succeeding and some failing' do
|
219
|
-
let(:http) { double(:
|
220
|
-
let(:notification) { Rpush::Adm::Notification.create!(:
|
221
|
-
let(:bad_request_response) { double(:
|
230
|
+
let(:http) { double(shutdown: nil) }
|
231
|
+
let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: %w(abc xyz), deliver_after: Time.now, collapse_key: 'sync', data: { 'message' => 'test' }) }
|
232
|
+
let(:bad_request_response) { double(code: 400, body: JSON.dump('reason' => 'InvalidData')) }
|
222
233
|
|
223
234
|
it 'should keep sent reg ids in original notification and create new notification with remaining reg ids for retry' do
|
224
|
-
response.stub(:
|
235
|
+
response.stub(code: 200, body: JSON.dump('registrationID' => 'abc'))
|
225
236
|
|
226
237
|
# first request to deliver message succeeds
|
227
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
238
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'abc'))
|
228
239
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
|
229
240
|
|
230
241
|
# first request to deliver message that returns too many request response
|
231
|
-
adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL
|
242
|
+
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'xyz'))
|
232
243
|
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(bad_request_response)
|
233
244
|
|
234
245
|
store.should_receive(:update_notification).with do |notif|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
|
-
describe Rpush::
|
4
|
-
let(:app) { double(:
|
5
|
-
let(:error) { Rpush::
|
3
|
+
describe Rpush::CertificateExpiredError do
|
4
|
+
let(:app) { double(name: 'test') }
|
5
|
+
let(:error) { Rpush::CertificateExpiredError.new(app, Time.now) }
|
6
6
|
|
7
7
|
it 'returns a message' do
|
8
8
|
error.message
|
@@ -1,101 +1,108 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Rpush::Daemon::Apns::Delivery do
|
4
|
-
let(:app) { double(:
|
5
|
-
let(:
|
6
|
-
let(:
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
let(:connection) { double(:
|
10
|
-
let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection,
|
11
|
-
|
12
|
-
def perform
|
13
|
-
begin
|
14
|
-
delivery.perform
|
15
|
-
rescue Rpush::DeliveryError, Rpush::Apns::DisconnectionError
|
16
|
-
end
|
17
|
-
end
|
4
|
+
let(:app) { double(name: 'MyApp') }
|
5
|
+
let(:notification1) { double.as_null_object }
|
6
|
+
let(:notification2) { double.as_null_object }
|
7
|
+
let(:batch) { double(mark_all_failed: nil, mark_all_delivered: nil, all_processed: nil) }
|
8
|
+
let(:logger) { double(error: nil, info: nil) }
|
9
|
+
let(:connection) { double(select: false, write: nil, reconnect: nil, close: nil, connect: nil) }
|
10
|
+
let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection, batch) }
|
18
11
|
|
19
12
|
before do
|
20
|
-
|
13
|
+
batch.stub(:each_notification) do |&blk|
|
14
|
+
[notification1, notification2].each(&blk)
|
15
|
+
end
|
16
|
+
Rpush.stub(logger: logger)
|
21
17
|
end
|
22
18
|
|
23
|
-
it
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
it 'writes the binary batch' do
|
20
|
+
notification1.stub(to_binary: 'binary1')
|
21
|
+
notification2.stub(to_binary: 'binary2')
|
22
|
+
connection.should_receive(:write).with('binary1binary2')
|
23
|
+
delivery.perform
|
27
24
|
end
|
28
25
|
|
29
|
-
it
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
it 'logs the notification deliveries' do
|
27
|
+
notification1.stub(id: 666, device_token: 'abc123')
|
28
|
+
notification2.stub(id: 42, device_token: 'abc456')
|
29
|
+
logger.should_receive(:info).with('[MyApp] 666 sent to abc123')
|
30
|
+
logger.should_receive(:info).with('[MyApp] 42 sent to abc456')
|
31
|
+
delivery.perform
|
33
32
|
end
|
34
33
|
|
35
|
-
it
|
36
|
-
delivery.should_receive(:
|
37
|
-
perform
|
34
|
+
it 'marks all notifications as delivered' do
|
35
|
+
delivery.should_receive(:mark_batch_delivered)
|
36
|
+
delivery.perform
|
38
37
|
end
|
39
38
|
|
40
|
-
it '
|
41
|
-
|
42
|
-
delivery.
|
43
|
-
perform
|
39
|
+
it 'notifies the batch all notifications have been processed' do
|
40
|
+
batch.should_receive(:all_processed)
|
41
|
+
delivery.perform
|
44
42
|
end
|
45
43
|
|
46
|
-
describe
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
delivery.should_receive(:
|
51
|
-
perform
|
52
|
-
end
|
53
|
-
|
54
|
-
it "logs the delivery error" do
|
55
|
-
# checking for the doublebed error doesn't work in jruby, but checking
|
56
|
-
# for the exception by class does.
|
57
|
-
|
58
|
-
#error = Rpush::DeliveryError.new(4, 12, "Missing payload")
|
59
|
-
#Rpush::DeliveryError.stub(:new => error)
|
60
|
-
#expect { delivery.perform }.to raise_error(error)
|
61
|
-
|
62
|
-
expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "reads 6 bytes from the socket" do
|
66
|
-
connection.should_receive(:read).with(6).and_return(nil)
|
67
|
-
perform
|
68
|
-
end
|
69
|
-
|
70
|
-
it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
|
71
|
-
connection.stub(:select => nil)
|
72
|
-
connection.should_not_receive(:read)
|
73
|
-
perform
|
74
|
-
end
|
75
|
-
|
76
|
-
it "reconnects the socket" do
|
77
|
-
connection.should_receive(:reconnect)
|
78
|
-
perform
|
79
|
-
end
|
80
|
-
|
81
|
-
it "logs that the connection is being reconnected" do
|
82
|
-
Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
|
83
|
-
perform
|
84
|
-
end
|
85
|
-
|
86
|
-
context "when the APNs disconnects without returning an error" do
|
87
|
-
before do
|
88
|
-
connection.stub(:read => nil)
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'raises a DisconnectError error if the connection is closed without an error being returned' do
|
92
|
-
expect { delivery.perform }.to raise_error(Rpush::Apns::DisconnectionError)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'marks the notification as failed' do
|
96
|
-
delivery.should_receive(:mark_failed).with(nil, "APNs disconnected without returning an error.")
|
97
|
-
perform
|
98
|
-
end
|
44
|
+
describe 'when an error is raised' do
|
45
|
+
it 'marks all notifications as failed' do
|
46
|
+
error = StandardError.new
|
47
|
+
connection.stub(:write).and_raise(error)
|
48
|
+
delivery.should_receive(:mark_batch_failed).with(error)
|
49
|
+
expect { delivery.perform }.to raise_error(error)
|
99
50
|
end
|
100
51
|
end
|
52
|
+
|
53
|
+
# describe "when delivery fails" do
|
54
|
+
# before { connection.stub(select: true, read: [8, 4, 69].pack("ccN")) }
|
55
|
+
#
|
56
|
+
# it "marks the notification as failed" do
|
57
|
+
# delivery.should_receive(:mark_failed).with(4, "Unable to deliver notification 69, received error 4 (Missing payload)")
|
58
|
+
# perform
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# it "logs the delivery error" do
|
62
|
+
# # checking for the doublebed error doesn't work in jruby, but checking
|
63
|
+
# # for the exception by class does.
|
64
|
+
#
|
65
|
+
# # error = Rpush::DeliveryError.new(4, 12, "Missing payload")
|
66
|
+
# # Rpush::DeliveryError.stub(new: error)
|
67
|
+
# # expect { delivery.perform }.to raise_error(error)
|
68
|
+
#
|
69
|
+
# expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# it "reads 6 bytes from the socket" do
|
73
|
+
# connection.should_receive(:read).with(6).and_return(nil)
|
74
|
+
# perform
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
|
78
|
+
# connection.stub(select: nil)
|
79
|
+
# connection.should_not_receive(:read)
|
80
|
+
# perform
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# it "reconnects the socket" do
|
84
|
+
# connection.should_receive(:reconnect)
|
85
|
+
# perform
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# it "logs that the connection is being reconnected" do
|
89
|
+
# Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
|
90
|
+
# perform
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# context "when the APNs disconnects without returning an error" do
|
94
|
+
# before do
|
95
|
+
# connection.stub(read: nil)
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# it 'raises a DisconnectError error if the connection is closed without an error being returned' do
|
99
|
+
# expect { delivery.perform }.to raise_error(Rpush::DisconnectionError)
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# it 'marks the notification as failed' do
|
103
|
+
# delivery.should_receive(:mark_failed).with(nil, "The APNs disconnected without returning an error. This may indicate you are using an invalid certificate for the host.")
|
104
|
+
# perform
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
# end
|
101
108
|
end
|