rpush 1.0.0 → 2.0.0.beta1
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 +12 -14
- data/bin/rpush +11 -2
- 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 +10 -7
- data/lib/generators/templates/rpush_2_0_0_updates.rb +23 -0
- data/lib/rpush.rb +4 -28
- data/lib/rpush/client/active_model.rb +21 -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_record.rb +19 -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 +20 -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/redis.rb +35 -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 +22 -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/configuration.rb +27 -6
- data/lib/rpush/daemon.rb +36 -56
- data/lib/rpush/daemon/adm/delivery.rb +50 -52
- data/lib/rpush/daemon/apns.rb +6 -5
- data/lib/rpush/daemon/apns/delivery.rb +20 -44
- data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
- data/lib/rpush/daemon/app_runner.rb +67 -60
- 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 +106 -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 +15 -6
- 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/ring_buffer.rb +16 -0
- data/lib/rpush/daemon/service_config_methods.rb +23 -7
- data/lib/rpush/daemon/signal_handler.rb +51 -0
- data/lib/rpush/daemon/store/active_record.rb +71 -38
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +15 -15
- data/lib/rpush/daemon/store/interface.rb +19 -0
- data/lib/rpush/daemon/store/redis.rb +149 -0
- data/lib/rpush/daemon/tcp_connection.rb +6 -11
- data/lib/rpush/daemon/wpns/delivery.rb +21 -30
- data/lib/rpush/deprecatable.rb +4 -3
- data/lib/rpush/deprecation.rb +7 -10
- data/lib/rpush/embed.rb +7 -2
- data/lib/rpush/logger.rb +11 -15
- data/lib/rpush/push.rb +0 -1
- data/lib/rpush/reflection.rb +6 -12
- data/lib/rpush/version.rb +1 -1
- data/lib/tasks/quality.rake +34 -0
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +3 -6
- data/spec/functional/apns_spec.rb +118 -24
- data/spec/functional/embed_spec.rb +22 -20
- data/spec/functional/gcm_spec.rb +4 -7
- data/spec/functional/new_app_spec.rb +61 -0
- data/spec/functional/retry_spec.rb +46 -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 +15 -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 +57 -54
- 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 +24 -17
- data/spec/unit/daemon/app_runner_spec.rb +66 -123
- 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 +7 -12
- data/spec/unit/daemon/feeder_spec.rb +40 -39
- data/spec/unit/daemon/gcm/delivery_spec.rb +108 -89
- 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 +72 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +9 -9
- 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/too_many_requests_error_spec.rb +1 -1
- data/spec/unit/daemon/wpns/delivery_spec.rb +61 -50
- data/spec/unit/daemon_spec.rb +46 -81
- data/spec/unit/embed_spec.rb +4 -2
- data/spec/unit/logger_spec.rb +30 -40
- data/spec/unit/notification_shared.rb +9 -79
- data/spec/unit/push_spec.rb +3 -8
- 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 +119 -67
- 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/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/interruptible_sleep_spec.rb +0 -68
- 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
|
@@ -16,7 +16,6 @@ describe Rpush::Daemon::Delivery do
|
|
|
16
16
|
before { Time.stub(now: now) }
|
|
17
17
|
|
|
18
18
|
describe 'mark_retryable' do
|
|
19
|
-
|
|
20
19
|
it 'does not retry a notification with an expired fail_after' do
|
|
21
20
|
batch.should_receive(:mark_failed).with(notification, nil, "Notification failed to be delivered before 2014-10-13 23:00:00.")
|
|
22
21
|
notification.fail_after = Time.now - 1.hour
|
|
@@ -35,4 +34,19 @@ describe Rpush::Daemon::Delivery do
|
|
|
35
34
|
delivery.mark_retryable(notification, Time.now + 1.hour)
|
|
36
35
|
end
|
|
37
36
|
end
|
|
37
|
+
|
|
38
|
+
describe 'mark_batch_delivered' do
|
|
39
|
+
it 'marks all notifications as delivered' do
|
|
40
|
+
batch.should_receive(:mark_all_delivered)
|
|
41
|
+
delivery.mark_batch_delivered
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'mark_batch_failed' do
|
|
46
|
+
it 'marks all notifications as delivered' do
|
|
47
|
+
error = Rpush::DeliveryError.new(1, 42, 'an error')
|
|
48
|
+
batch.should_receive(:mark_all_failed).with(1, 'Unable to deliver notification 42, received error 1 (an error)')
|
|
49
|
+
delivery.mark_batch_failed(error)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
38
52
|
end
|
|
@@ -6,9 +6,10 @@ describe Rpush::Daemon::Dispatcher::Http do
|
|
|
6
6
|
let(:notification) { double }
|
|
7
7
|
let(:batch) { double }
|
|
8
8
|
let(:http) { double }
|
|
9
|
+
let(:queue_payload) { Rpush::Daemon::QueuePayload.new(batch, notification) }
|
|
9
10
|
let(:dispatcher) { Rpush::Daemon::Dispatcher::Http.new(app, delivery_class) }
|
|
10
11
|
|
|
11
|
-
before { Net::HTTP::Persistent.stub(:
|
|
12
|
+
before { Net::HTTP::Persistent.stub(new: http) }
|
|
12
13
|
|
|
13
14
|
it 'constructs a new persistent connection' do
|
|
14
15
|
Net::HTTP::Persistent.should_receive(:new)
|
|
@@ -20,7 +21,7 @@ describe Rpush::Daemon::Dispatcher::Http do
|
|
|
20
21
|
delivery = double
|
|
21
22
|
delivery_class.should_receive(:new).with(app, http, notification, batch).and_return(delivery)
|
|
22
23
|
delivery.should_receive(:perform)
|
|
23
|
-
dispatcher.dispatch(
|
|
24
|
+
dispatcher.dispatch(queue_payload)
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -2,35 +2,36 @@ require 'unit_spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe Rpush::Daemon::Dispatcher::Tcp do
|
|
4
4
|
let(:app) { double }
|
|
5
|
-
let(:delivery) { double(:
|
|
6
|
-
let(:delivery_class) { double(:
|
|
5
|
+
let(:delivery) { double(perform: nil) }
|
|
6
|
+
let(:delivery_class) { double(new: delivery) }
|
|
7
7
|
let(:notification) { double }
|
|
8
8
|
let(:batch) { double }
|
|
9
|
-
let(:connection) { double(Rpush::Daemon::TcpConnection, :
|
|
9
|
+
let(:connection) { double(Rpush::Daemon::TcpConnection, connect: nil) }
|
|
10
10
|
let(:host) { 'localhost' }
|
|
11
11
|
let(:port) { 1234 }
|
|
12
|
-
let(:host_proc) {
|
|
13
|
-
let(:
|
|
12
|
+
let(:host_proc) { proc { [host, port] } }
|
|
13
|
+
let(:queue_payload) { Rpush::Daemon::QueuePayload.new(batch, notification) }
|
|
14
|
+
let(:dispatcher) { Rpush::Daemon::Dispatcher::Tcp.new(app, delivery_class, host: host_proc) }
|
|
14
15
|
|
|
15
|
-
before { Rpush::Daemon::TcpConnection.stub(:
|
|
16
|
+
before { Rpush::Daemon::TcpConnection.stub(new: connection) }
|
|
16
17
|
|
|
17
18
|
describe 'dispatch' do
|
|
18
19
|
it 'lazily connects the socket' do
|
|
19
20
|
Rpush::Daemon::TcpConnection.should_receive(:new).with(app, host, port).and_return(connection)
|
|
20
21
|
connection.should_receive(:connect)
|
|
21
|
-
dispatcher.dispatch(
|
|
22
|
+
dispatcher.dispatch(queue_payload)
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
it 'delivers the notification' do
|
|
25
26
|
delivery_class.should_receive(:new).with(app, connection, notification, batch).and_return(delivery)
|
|
26
27
|
delivery.should_receive(:perform)
|
|
27
|
-
dispatcher.dispatch(
|
|
28
|
+
dispatcher.dispatch(queue_payload)
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
describe 'cleanup' do
|
|
32
33
|
it 'closes the connection' do
|
|
33
|
-
dispatcher.dispatch(
|
|
34
|
+
dispatcher.dispatch(queue_payload) # lazily initialize connection
|
|
34
35
|
connection.should_receive(:close)
|
|
35
36
|
dispatcher.cleanup
|
|
36
37
|
end
|
|
@@ -9,20 +9,20 @@ describe Rpush::Daemon::DispatcherLoop do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
let(:notification) { double }
|
|
12
|
-
let(:batch) { double(:
|
|
12
|
+
let(:batch) { double(notification_processed: nil) }
|
|
13
13
|
let(:queue) { Queue.new }
|
|
14
|
-
let(:dispatcher) { double(:
|
|
14
|
+
let(:dispatcher) { double(dispatch: nil, cleanup: nil) }
|
|
15
15
|
let(:dispatcher_loop) { Rpush::Daemon::DispatcherLoop.new(queue, dispatcher) }
|
|
16
|
-
let(:store) { double(Rpush::Daemon::Store::ActiveRecord, release_connection: nil)}
|
|
16
|
+
let(:store) { double(Rpush::Daemon::Store::ActiveRecord, release_connection: nil) }
|
|
17
17
|
|
|
18
18
|
before do
|
|
19
|
-
Rpush::Daemon.stub(:
|
|
19
|
+
Rpush::Daemon.stub(store: store)
|
|
20
20
|
queue.push([notification, batch])
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
it 'logs errors' do
|
|
24
24
|
logger = double
|
|
25
|
-
Rpush.stub(:
|
|
25
|
+
Rpush.stub(logger: logger)
|
|
26
26
|
error = StandardError.new
|
|
27
27
|
dispatcher.stub(:dispatch).and_raise(error)
|
|
28
28
|
Rpush.logger.should_receive(:error).with(error)
|
|
@@ -30,19 +30,14 @@ describe Rpush::Daemon::DispatcherLoop do
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it 'reflects an exception' do
|
|
33
|
-
Rpush.stub(:
|
|
33
|
+
Rpush.stub(logger: double(error: nil))
|
|
34
34
|
error = StandardError.new
|
|
35
35
|
dispatcher.stub(:dispatch).and_raise(error)
|
|
36
36
|
dispatcher_loop.should_receive(:reflect).with(:error, error)
|
|
37
37
|
run_dispatcher_loop
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
it 'instructs the
|
|
41
|
-
batch.should_receive(:notification_dispatched)
|
|
42
|
-
run_dispatcher_loop
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it "instructs the queue to wakeup the thread when told to stop" do
|
|
40
|
+
it 'instructs the queue to wakeup the thread when told to stop' do
|
|
46
41
|
queue.should_receive(:push).with(Rpush::Daemon::DispatcherLoop::WAKEUP).and_call_original
|
|
47
42
|
run_dispatcher_loop
|
|
48
43
|
end
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
require "unit_spec_helper"
|
|
2
2
|
|
|
3
3
|
describe Rpush::Daemon::Feeder do
|
|
4
|
-
let(:
|
|
5
|
-
|
|
6
|
-
:embedded => false,
|
|
7
|
-
:push => false,
|
|
8
|
-
:wakeup => nil) }
|
|
9
|
-
let!(:app) { Rpush::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
|
|
10
|
-
let(:notification) { Rpush::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
|
|
4
|
+
let!(:app) { Rpush::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
|
|
5
|
+
let(:notification) { Rpush::Apns::Notification.create!(device_token: "a" * 64, app: app) }
|
|
11
6
|
let(:logger) { double }
|
|
12
|
-
let(:
|
|
13
|
-
let(:store)
|
|
14
|
-
|
|
7
|
+
let(:interruptible_sleeper) { double(sleep: nil, stop: nil, start: nil) }
|
|
8
|
+
let(:store) do double(Rpush::Daemon::Store::ActiveRecord,
|
|
9
|
+
deliverable_notifications: [notification], release_connection: nil)
|
|
10
|
+
end
|
|
15
11
|
|
|
16
12
|
before do
|
|
17
|
-
Rpush.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
Rpush.configure do |config|
|
|
14
|
+
config.batch_size = 5000
|
|
15
|
+
config.push_poll = 0
|
|
16
|
+
config.push = false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Rpush.stub(logger: logger)
|
|
20
|
+
Rpush::Daemon.stub(store: store)
|
|
21
|
+
Rpush::Daemon::Feeder.stub(should_stop: true, interruptible_sleeper: interruptible_sleeper)
|
|
22
|
+
Rpush::Daemon::AppRunner.stub(enqueue: nil, num_queued: 0)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def start_and_stop
|
|
@@ -27,26 +27,26 @@ describe Rpush::Daemon::Feeder do
|
|
|
27
27
|
Rpush::Daemon::Feeder.stop
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
it '
|
|
31
|
-
|
|
32
|
-
Thread.should_receive(:new).and_yield
|
|
33
|
-
Rpush::Daemon::Feeder.should_receive(:feed_forever)
|
|
30
|
+
it 'loads deliverable notifications' do
|
|
31
|
+
Rpush::Daemon.store.should_receive(:deliverable_notifications).with(Rpush.config.batch_size)
|
|
34
32
|
start_and_stop
|
|
35
33
|
end
|
|
36
34
|
|
|
37
|
-
it '
|
|
38
|
-
Rpush::Daemon.
|
|
35
|
+
it 'does not load more notifications if the total queue size is equal to the batch size' do
|
|
36
|
+
Rpush::Daemon::AppRunner.stub(num_queued: Rpush.config.batch_size)
|
|
37
|
+
Rpush::Daemon.store.should_not_receive(:deliverable_notifications)
|
|
39
38
|
start_and_stop
|
|
40
39
|
end
|
|
41
40
|
|
|
42
|
-
it '
|
|
43
|
-
Rpush
|
|
44
|
-
Rpush::Daemon.
|
|
41
|
+
it 'limits the batch size if some runners are still processing notifications' do
|
|
42
|
+
Rpush.config.stub(batch_size: 10)
|
|
43
|
+
Rpush::Daemon::AppRunner.stub(num_queued: 6)
|
|
44
|
+
Rpush::Daemon.store.should_receive(:deliverable_notifications).with(4)
|
|
45
45
|
start_and_stop
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it 'enqueues notifications without looping if in push mode' do
|
|
49
|
-
config.
|
|
49
|
+
Rpush.config.push = true
|
|
50
50
|
Rpush::Daemon::Feeder.should_not_receive(:feed_forever)
|
|
51
51
|
Rpush::Daemon::Feeder.should_receive(:enqueue_notifications)
|
|
52
52
|
start_and_stop
|
|
@@ -65,34 +65,35 @@ describe Rpush::Daemon::Feeder do
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
describe 'stop' do
|
|
68
|
-
it 'interrupts sleep
|
|
69
|
-
|
|
68
|
+
it 'interrupts sleep' do
|
|
69
|
+
interruptible_sleeper.should_receive(:stop)
|
|
70
70
|
start_and_stop
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
it 'releases the store connection
|
|
73
|
+
it 'releases the store connection' do
|
|
74
74
|
Rpush::Daemon.store.should_receive(:release_connection)
|
|
75
75
|
start_and_stop
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
it
|
|
79
|
+
it 'enqueues notifications when started' do
|
|
80
80
|
Rpush::Daemon::Feeder.should_receive(:enqueue_notifications).at_least(:once)
|
|
81
81
|
Rpush::Daemon::Feeder.stub(:loop).and_yield
|
|
82
82
|
start_and_stop
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
it
|
|
86
|
-
|
|
87
|
-
interruptible_sleep.should_receive(:sleep).with(2)
|
|
85
|
+
it 'sleeps' do
|
|
86
|
+
interruptible_sleeper.should_receive(:sleep)
|
|
88
87
|
start_and_stop
|
|
89
88
|
end
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
describe 'wakeup' do
|
|
91
|
+
it 'interrupts sleep' do
|
|
92
|
+
interruptible_sleeper.should_receive(:wakeup)
|
|
93
|
+
Rpush::Daemon::Feeder.start
|
|
94
|
+
Rpush::Daemon::Feeder.wakeup
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
after { Rpush::Daemon::Feeder.stop }
|
|
97
98
|
end
|
|
98
99
|
end
|
|
@@ -1,44 +1,51 @@
|
|
|
1
1
|
require 'unit_spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Rpush::Daemon::Gcm::Delivery do
|
|
4
|
-
let(:app) { Rpush::Gcm::App.
|
|
5
|
-
let(:notification) { Rpush::Gcm::Notification.create!(:
|
|
6
|
-
let(:logger) { double(:
|
|
7
|
-
let(:response) { double(:
|
|
8
|
-
let(:http) { double(:
|
|
4
|
+
let(:app) { Rpush::Gcm::App.create!(name: 'MyApp', auth_key: 'abc123') }
|
|
5
|
+
let(:notification) { Rpush::Gcm::Notification.create!(app: app, registration_ids: ['xyz'], deliver_after: Time.now) }
|
|
6
|
+
let(:logger) { double(error: nil, info: nil, warn: nil) }
|
|
7
|
+
let(:response) { double(code: 200, header: {}) }
|
|
8
|
+
let(:http) { double(shutdown: nil, request: response) }
|
|
9
9
|
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
|
10
|
-
let(:batch) { double(:
|
|
10
|
+
let(:batch) { double(mark_failed: nil, mark_delivered: nil, mark_retryable: nil, notification_processed: nil) }
|
|
11
11
|
let(:delivery) { Rpush::Daemon::Gcm::Delivery.new(app, http, notification, batch) }
|
|
12
|
-
let(:store) { double(:
|
|
12
|
+
let(:store) { double(create_gcm_notification: double(id: 2)) }
|
|
13
13
|
|
|
14
14
|
def perform
|
|
15
15
|
delivery.perform
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def perform_with_rescue
|
|
19
|
+
expect { perform }.to raise_error
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
before do
|
|
19
|
-
delivery.stub(:
|
|
20
|
-
Rpush::Daemon.stub(:
|
|
21
|
-
Time.stub(:
|
|
22
|
-
Rpush.stub(:
|
|
23
|
+
delivery.stub(reflect: nil)
|
|
24
|
+
Rpush::Daemon.stub(store: store)
|
|
25
|
+
Time.stub(now: now)
|
|
26
|
+
Rpush.stub(logger: logger)
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
shared_examples_for 'a notification with some delivery failures' do
|
|
26
30
|
let(:new_notification) { Rpush::Gcm::Notification.where('id != ?', notification.id).first }
|
|
27
31
|
|
|
28
|
-
before { response.stub(:
|
|
32
|
+
before { response.stub(body: JSON.dump(body)) }
|
|
29
33
|
|
|
30
34
|
it 'marks the original notification as failed' do
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
# error = Rpush::DeliveryError.new(nil, notification.id, error_description)
|
|
36
|
+
delivery.should_receive(:mark_failed) do |error|
|
|
37
|
+
error.to_s.should =~ error_description
|
|
38
|
+
end
|
|
39
|
+
perform_with_rescue
|
|
33
40
|
end
|
|
34
41
|
|
|
35
42
|
it 'creates a new notification for the unavailable devices' do
|
|
36
|
-
notification.update_attributes(:
|
|
37
|
-
response.stub(:
|
|
43
|
+
notification.update_attributes(registration_ids: %w(id_0 id_1 id_2), data: { 'one' => 1 }, collapse_key: 'thing', delay_while_idle: true)
|
|
44
|
+
response.stub(header: { 'retry-after' => 10 })
|
|
38
45
|
attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
|
|
39
46
|
store.should_receive(:create_gcm_notification).with(attrs, notification.data,
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
%w(id_0 id_2), now + 10.seconds, notification.app)
|
|
48
|
+
perform_with_rescue
|
|
42
49
|
end
|
|
43
50
|
|
|
44
51
|
it 'raises a DeliveryError' do
|
|
@@ -48,7 +55,7 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
48
55
|
|
|
49
56
|
describe 'a 200 response' do
|
|
50
57
|
before do
|
|
51
|
-
response.stub(:
|
|
58
|
+
response.stub(code: 200)
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
it 'reflects on any IDs which successfully received the notification' do
|
|
@@ -61,11 +68,11 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
61
68
|
]
|
|
62
69
|
}
|
|
63
70
|
|
|
64
|
-
response.stub(:
|
|
65
|
-
notification.stub(:
|
|
71
|
+
response.stub(body: JSON.dump(body))
|
|
72
|
+
notification.stub(registration_ids: %w(1 2))
|
|
66
73
|
delivery.should_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '1')
|
|
67
74
|
delivery.should_not_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '2')
|
|
68
|
-
|
|
75
|
+
perform_with_rescue
|
|
69
76
|
end
|
|
70
77
|
|
|
71
78
|
it 'reflects on any IDs which failed to receive the notification' do
|
|
@@ -78,11 +85,11 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
78
85
|
]
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
response.stub(:
|
|
82
|
-
notification.stub(:
|
|
88
|
+
response.stub(body: JSON.dump(body))
|
|
89
|
+
notification.stub(registration_ids: %w(1 2))
|
|
83
90
|
delivery.should_receive(:reflect).with(:gcm_failed_to_recipient, notification, 'Err', '1')
|
|
84
91
|
delivery.should_not_receive(:reflect).with(:gcm_failed_to_recipient, notification, anything, '2')
|
|
85
|
-
|
|
92
|
+
perform_with_rescue
|
|
86
93
|
end
|
|
87
94
|
|
|
88
95
|
it 'reflects on canonical IDs' do
|
|
@@ -93,40 +100,43 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
93
100
|
'results' => [
|
|
94
101
|
{ 'message_id' => '1:000' },
|
|
95
102
|
{ 'message_id' => '1:000', 'registration_id' => 'canonical123' },
|
|
96
|
-
{ 'message_id' => '1:000' }
|
|
97
|
-
]}
|
|
103
|
+
{ 'message_id' => '1:000' }
|
|
104
|
+
] }
|
|
98
105
|
|
|
99
|
-
response.stub(:
|
|
100
|
-
notification.stub(:
|
|
106
|
+
response.stub(body: JSON.dump(body))
|
|
107
|
+
notification.stub(registration_ids: %w(1 2 3))
|
|
101
108
|
delivery.should_receive(:reflect).with(:gcm_canonical_id, '2', 'canonical123')
|
|
102
109
|
perform
|
|
103
110
|
end
|
|
104
111
|
|
|
105
112
|
it 'reflects on invalid IDs' do
|
|
106
113
|
body = {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
'failure' => 1,
|
|
115
|
+
'success' => 2,
|
|
116
|
+
'canonical_ids' => 0,
|
|
117
|
+
'results' => [
|
|
118
|
+
{ 'message_id' => '1:000' },
|
|
119
|
+
{ 'error' => 'NotRegistered' },
|
|
120
|
+
{ 'message_id' => '1:000' }
|
|
121
|
+
]
|
|
122
|
+
}
|
|
115
123
|
|
|
116
|
-
response.stub(:
|
|
117
|
-
notification.stub(:
|
|
124
|
+
response.stub(body: JSON.dump(body))
|
|
125
|
+
notification.stub(registration_ids: %w(1 2 3))
|
|
118
126
|
delivery.should_receive(:reflect).with(:gcm_invalid_registration_id, app, 'NotRegistered', '2')
|
|
119
|
-
|
|
127
|
+
perform_with_rescue
|
|
120
128
|
end
|
|
121
129
|
|
|
122
130
|
describe 'when delivered successfully to all devices' do
|
|
123
|
-
let(:body)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
let(:body) do
|
|
132
|
+
{
|
|
133
|
+
'failure' => 0,
|
|
134
|
+
'success' => 1,
|
|
135
|
+
'results' => [{ 'message_id' => '1:000' }]
|
|
136
|
+
}
|
|
137
|
+
end
|
|
128
138
|
|
|
129
|
-
before { response.stub(:
|
|
139
|
+
before { response.stub(body: JSON.dump(body)) }
|
|
130
140
|
|
|
131
141
|
it 'marks the notification as delivered' do
|
|
132
142
|
delivery.should_receive(:mark_delivered)
|
|
@@ -141,20 +151,21 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
141
151
|
|
|
142
152
|
it 'marks a notification as failed if any ids are invalid' do
|
|
143
153
|
body = {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
'failure' => 1,
|
|
155
|
+
'success' => 2,
|
|
156
|
+
'canonical_ids' => 0,
|
|
157
|
+
'results' => [
|
|
158
|
+
{ 'message_id' => '1:000' },
|
|
159
|
+
{ 'error' => 'NotRegistered' },
|
|
160
|
+
{ 'message_id' => '1:000' }
|
|
161
|
+
]
|
|
162
|
+
}
|
|
152
163
|
|
|
153
|
-
response.stub(:
|
|
164
|
+
response.stub(body: JSON.dump(body))
|
|
154
165
|
delivery.should_receive(:mark_failed)
|
|
155
166
|
delivery.should_not_receive(:mark_retryable)
|
|
156
167
|
store.should_not_receive(:create_gcm_notification)
|
|
157
|
-
|
|
168
|
+
perform_with_rescue
|
|
158
169
|
end
|
|
159
170
|
|
|
160
171
|
it 'marks a notification as failed if any deliveries failed that cannot be retried' do
|
|
@@ -164,28 +175,32 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
164
175
|
'results' => [
|
|
165
176
|
{ 'message_id' => '1:000' },
|
|
166
177
|
{ 'error' => 'InvalidDataKey' }
|
|
167
|
-
]}
|
|
168
|
-
response.stub(:
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
] }
|
|
179
|
+
response.stub(body: JSON.dump(body))
|
|
180
|
+
error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients. Errors: InvalidDataKey.')
|
|
181
|
+
delivery.should_receive(:mark_failed).with(error)
|
|
182
|
+
perform_with_rescue
|
|
171
183
|
end
|
|
172
184
|
|
|
173
185
|
describe 'all deliveries failed with Unavailable or InternalServerError' do
|
|
174
|
-
let(:body)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
186
|
+
let(:body) do
|
|
187
|
+
{
|
|
188
|
+
'failure' => 2,
|
|
189
|
+
'success' => 0,
|
|
190
|
+
'results' => [
|
|
191
|
+
{ 'error' => 'Unavailable' },
|
|
192
|
+
{ 'error' => 'Unavailable' }
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
end
|
|
181
196
|
|
|
182
197
|
before do
|
|
183
|
-
response.stub(:
|
|
184
|
-
notification.stub(:
|
|
198
|
+
response.stub(body: JSON.dump(body))
|
|
199
|
+
notification.stub(registration_ids: %w(1 2))
|
|
185
200
|
end
|
|
186
201
|
|
|
187
202
|
it 'retries the notification respecting the Retry-After header' do
|
|
188
|
-
response.stub(:
|
|
203
|
+
response.stub(header: { 'retry-after' => 10 })
|
|
189
204
|
delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
|
190
205
|
perform
|
|
191
206
|
end
|
|
@@ -209,34 +224,36 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
209
224
|
end
|
|
210
225
|
|
|
211
226
|
describe 'all deliveries failed with some as Unavailable or InternalServerError' do
|
|
212
|
-
let(:body) {
|
|
227
|
+
let(:body) do{
|
|
213
228
|
'failure' => 3,
|
|
214
229
|
'success' => 0,
|
|
215
230
|
'results' => [
|
|
216
231
|
{ 'error' => 'Unavailable' },
|
|
217
232
|
{ 'error' => 'InvalidDataKey' },
|
|
218
233
|
{ 'error' => 'Unavailable' }
|
|
219
|
-
]}
|
|
234
|
+
] }
|
|
235
|
+
end
|
|
220
236
|
let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 1, 2. Errors: Unavailable, InvalidDataKey, Unavailable. 0, 2 will be retried as notification")} [\d]+\./ }
|
|
221
237
|
it_should_behave_like 'a notification with some delivery failures'
|
|
222
238
|
end
|
|
223
239
|
|
|
224
240
|
describe 'some deliveries failed with Unavailable or InternalServerError' do
|
|
225
|
-
let(:body) {
|
|
241
|
+
let(:body) do{
|
|
226
242
|
'failure' => 2,
|
|
227
243
|
'success' => 1,
|
|
228
244
|
'results' => [
|
|
229
245
|
{ 'error' => 'Unavailable' },
|
|
230
246
|
{ 'message_id' => '1:000' },
|
|
231
247
|
{ 'error' => 'InternalServerError' }
|
|
232
|
-
]}
|
|
248
|
+
] }
|
|
249
|
+
end
|
|
233
250
|
let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 2. Errors: Unavailable, InternalServerError. 0, 2 will be retried as notification")} [\d]+\./ }
|
|
234
251
|
it_should_behave_like 'a notification with some delivery failures'
|
|
235
252
|
end
|
|
236
253
|
end
|
|
237
254
|
|
|
238
255
|
describe 'a 503 response' do
|
|
239
|
-
before { response.stub(:
|
|
256
|
+
before { response.stub(code: 503) }
|
|
240
257
|
|
|
241
258
|
it 'logs a warning that the notification will be retried.' do
|
|
242
259
|
notification.retries = 1
|
|
@@ -246,19 +263,19 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
246
263
|
end
|
|
247
264
|
|
|
248
265
|
it 'respects an integer Retry-After header' do
|
|
249
|
-
response.stub(:
|
|
266
|
+
response.stub(header: { 'retry-after' => 10 })
|
|
250
267
|
delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
|
|
251
268
|
perform
|
|
252
269
|
end
|
|
253
270
|
|
|
254
271
|
it 'respects a HTTP-date Retry-After header' do
|
|
255
|
-
response.stub(:
|
|
272
|
+
response.stub(header: { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
|
|
256
273
|
delivery.should_receive(:mark_retryable).with(notification, Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
|
|
257
274
|
perform
|
|
258
275
|
end
|
|
259
276
|
|
|
260
277
|
it 'defaults to exponential back-off if the Retry-After header is not present' do
|
|
261
|
-
delivery.should_receive(:mark_retryable).with(notification, now + 2
|
|
278
|
+
delivery.should_receive(:mark_retryable).with(notification, now + 2**1)
|
|
262
279
|
perform
|
|
263
280
|
end
|
|
264
281
|
end
|
|
@@ -266,24 +283,24 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
266
283
|
describe 'a 500 response' do
|
|
267
284
|
before do
|
|
268
285
|
notification.update_attribute(:retries, 2)
|
|
269
|
-
response.stub(:
|
|
286
|
+
response.stub(code: 500)
|
|
270
287
|
end
|
|
271
288
|
|
|
272
289
|
it 'logs a warning that the notification has been re-queued.' do
|
|
273
290
|
notification.retries = 3
|
|
274
|
-
notification.deliver_after = now + 2
|
|
275
|
-
Rpush.logger.should_receive(:warn).with("[MyApp] GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2
|
|
291
|
+
notification.deliver_after = now + 2**3
|
|
292
|
+
Rpush.logger.should_receive(:warn).with("[MyApp] GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2**3).strftime("%Y-%m-%d %H:%M:%S")} (retry 3).")
|
|
276
293
|
perform
|
|
277
294
|
end
|
|
278
295
|
|
|
279
296
|
it 'retries the notification in accordance with the exponential back-off strategy.' do
|
|
280
|
-
delivery.should_receive(:mark_retryable).with(notification, now + 2
|
|
297
|
+
delivery.should_receive(:mark_retryable).with(notification, now + 2**3)
|
|
281
298
|
perform
|
|
282
299
|
end
|
|
283
300
|
end
|
|
284
301
|
|
|
285
302
|
describe 'a 401 response' do
|
|
286
|
-
before { response.stub(:
|
|
303
|
+
before { response.stub(code: 401) }
|
|
287
304
|
|
|
288
305
|
it 'raises an error' do
|
|
289
306
|
expect { perform }.to raise_error(Rpush::DeliveryError)
|
|
@@ -291,20 +308,22 @@ describe Rpush::Daemon::Gcm::Delivery do
|
|
|
291
308
|
end
|
|
292
309
|
|
|
293
310
|
describe 'a 400 response' do
|
|
294
|
-
before { response.stub(:
|
|
311
|
+
before { response.stub(code: 400) }
|
|
295
312
|
|
|
296
313
|
it 'marks the notification as failed' do
|
|
297
|
-
|
|
298
|
-
|
|
314
|
+
error = Rpush::DeliveryError.new(400, notification.id, 'GCM failed to parse the JSON request. Possibly an Rpush bug, please open an issue.')
|
|
315
|
+
delivery.should_receive(:mark_failed).with(error)
|
|
316
|
+
perform_with_rescue
|
|
299
317
|
end
|
|
300
318
|
end
|
|
301
319
|
|
|
302
320
|
describe 'an un-handled response' do
|
|
303
|
-
before { response.stub(:
|
|
321
|
+
before { response.stub(code: 418) }
|
|
304
322
|
|
|
305
323
|
it 'marks the notification as failed' do
|
|
306
|
-
|
|
307
|
-
|
|
324
|
+
error = Rpush::DeliveryError.new(418, notification.id, "I'm a Teapot")
|
|
325
|
+
delivery.should_receive(:mark_failed).with(error)
|
|
326
|
+
perform_with_rescue
|
|
308
327
|
end
|
|
309
328
|
end
|
|
310
329
|
end
|