rpush 2.4.0-java → 2.6.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 +27 -1
- data/README.md +18 -8
- data/lib/generators/rpush_migration_generator.rb +1 -0
- data/lib/generators/templates/rpush.rb +8 -2
- data/lib/generators/templates/rpush_2_0_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
- data/lib/rpush/cli.rb +63 -27
- data/lib/rpush/client/active_model.rb +3 -0
- data/lib/rpush/client/active_model/apns/notification.rb +1 -1
- data/lib/rpush/client/active_model/gcm/notification.rb +1 -0
- data/lib/rpush/client/active_model/wns/app.rb +23 -0
- data/lib/rpush/client/active_model/wns/notification.rb +28 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +11 -6
- data/lib/rpush/client/active_record.rb +3 -0
- data/lib/rpush/client/active_record/notification.rb +1 -1
- data/lib/rpush/client/active_record/wns/app.rb +11 -0
- data/lib/rpush/client/active_record/wns/notification.rb +11 -0
- data/lib/rpush/client/mongoid.rb +3 -0
- data/lib/rpush/client/mongoid/apns/feedback.rb +3 -0
- data/lib/rpush/client/mongoid/notification.rb +7 -0
- data/lib/rpush/client/mongoid/wns/app.rb +14 -0
- data/lib/rpush/client/mongoid/wns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +3 -0
- data/lib/rpush/client/redis/notification.rb +1 -0
- data/lib/rpush/client/redis/wns/app.rb +14 -0
- data/lib/rpush/client/redis/wns/notification.rb +11 -0
- data/lib/rpush/configuration.rb +3 -7
- data/lib/rpush/daemon.rb +9 -0
- data/lib/rpush/daemon/apns/feedback_receiver.rb +5 -0
- data/lib/rpush/daemon/app_runner.rb +4 -5
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +47 -12
- data/lib/rpush/daemon/dispatcher_loop.rb +5 -0
- data/lib/rpush/daemon/feeder.rb +11 -0
- data/lib/rpush/daemon/gcm/delivery.rb +2 -2
- data/lib/rpush/daemon/interruptible_sleep.rb +8 -3
- data/lib/rpush/daemon/loggable.rb +4 -0
- data/lib/rpush/daemon/rpc.rb +9 -0
- data/lib/rpush/daemon/rpc/client.rb +27 -0
- data/lib/rpush/daemon/rpc/server.rb +82 -0
- data/lib/rpush/daemon/signal_handler.rb +7 -0
- data/lib/rpush/daemon/store/active_record.rb +17 -3
- data/lib/rpush/daemon/store/mongoid.rb +2 -2
- data/lib/rpush/daemon/store/redis.rb +2 -2
- data/lib/rpush/daemon/tcp_connection.rb +2 -2
- data/lib/rpush/daemon/wns.rb +9 -0
- data/lib/rpush/daemon/wns/delivery.rb +204 -0
- data/lib/rpush/embed.rb +15 -13
- data/lib/rpush/logger.rb +4 -0
- data/lib/rpush/plugin.rb +1 -1
- data/lib/rpush/push.rb +2 -11
- data/lib/rpush/reflection_collection.rb +15 -17
- data/lib/rpush/reflection_public_methods.rb +6 -4
- data/lib/rpush/version.rb +1 -1
- data/spec/functional/apns_spec.rb +1 -11
- data/spec/functional/cli_spec.rb +36 -0
- data/spec/functional_spec_helper.rb +11 -1
- data/spec/spec_helper.rb +4 -3
- data/spec/support/active_record_setup.rb +3 -2
- data/spec/unit/client/active_record/apns/notification_spec.rb +1 -1
- data/spec/unit/client/active_record/gcm/notification_spec.rb +5 -0
- data/spec/unit/configuration_spec.rb +0 -7
- data/spec/unit/daemon/adm/delivery_spec.rb +2 -2
- data/spec/unit/daemon/app_runner_spec.rb +2 -3
- data/spec/unit/daemon/gcm/delivery_spec.rb +1 -1
- data/spec/unit/daemon/tcp_connection_spec.rb +1 -1
- data/spec/unit/daemon/wns/delivery_spec.rb +171 -0
- data/spec/unit/daemon/wpns/delivery_spec.rb +1 -1
- data/spec/unit/daemon_spec.rb +2 -0
- data/spec/unit/embed_spec.rb +4 -11
- data/spec/unit/logger_spec.rb +2 -2
- data/spec/unit/push_spec.rb +0 -7
- data/spec/unit_spec_helper.rb +1 -1
- metadata +20 -2
data/lib/rpush/embed.rb
CHANGED
@@ -1,21 +1,13 @@
|
|
1
1
|
module Rpush
|
2
|
-
def self.embed
|
2
|
+
def self.embed
|
3
3
|
require 'rpush/daemon'
|
4
4
|
|
5
|
-
unless options.empty?
|
6
|
-
warning = "Passing configuration options directly to Rpush.embed is deprecated and will be removed from Rpush 2.5.0. Please setup configuration using Rpush.configure { |config| ... } before calling embed."
|
7
|
-
Rpush::Deprecation.warn_with_backtrace(warning)
|
8
|
-
end
|
9
|
-
|
10
5
|
if @embed_thread
|
11
6
|
STDERR.puts 'Rpush.embed can only be run once inside this process.'
|
12
7
|
end
|
13
8
|
|
14
|
-
config =
|
15
|
-
|
16
|
-
config.embedded = true
|
17
|
-
config.foreground = true
|
18
|
-
Rpush.config.update(config)
|
9
|
+
Rpush.config.embedded = true
|
10
|
+
Rpush.config.foreground = true
|
19
11
|
Kernel.at_exit { shutdown }
|
20
12
|
@embed_thread = Thread.new { Rpush::Daemon.start }
|
21
13
|
end
|
@@ -24,6 +16,10 @@ module Rpush
|
|
24
16
|
return unless Rpush.config.embedded
|
25
17
|
Rpush::Daemon.shutdown
|
26
18
|
@embed_thread.join if @embed_thread
|
19
|
+
rescue StandardError => e
|
20
|
+
STDERR.puts(e.message)
|
21
|
+
STDERR.puts(e.backtrace.join("\n"))
|
22
|
+
ensure
|
27
23
|
@embed_thread = nil
|
28
24
|
end
|
29
25
|
|
@@ -32,8 +28,14 @@ module Rpush
|
|
32
28
|
Rpush::Daemon::Synchronizer.sync
|
33
29
|
end
|
34
30
|
|
35
|
-
def self.
|
31
|
+
def self.status
|
36
32
|
return unless Rpush.config.embedded
|
37
|
-
Rpush::Daemon::AppRunner.
|
33
|
+
status = Rpush::Daemon::AppRunner.status
|
34
|
+
Rpush.logger.info(JSON.pretty_generate(status))
|
35
|
+
status
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.debug
|
39
|
+
status
|
38
40
|
end
|
39
41
|
end
|
data/lib/rpush/logger.rb
CHANGED
data/lib/rpush/plugin.rb
CHANGED
data/lib/rpush/push.rb
CHANGED
@@ -1,17 +1,8 @@
|
|
1
1
|
module Rpush
|
2
|
-
def self.push
|
2
|
+
def self.push
|
3
3
|
require 'rpush/daemon'
|
4
4
|
|
5
|
-
|
6
|
-
warning = "Passing configuration options directly to Rpush.push is deprecated and will be removed from Rpush 2.5.0. Please setup configuration using Rpush.configure { |config| ... } before calling push."
|
7
|
-
Rpush::Deprecation.warn_with_backtrace(warning)
|
8
|
-
end
|
9
|
-
|
10
|
-
config = Rpush::ConfigurationWithoutDefaults.new
|
11
|
-
options.each { |k, v| config.send("#{k}=", v) }
|
12
|
-
config.push = true
|
13
|
-
Rpush.config.update(config)
|
14
|
-
|
5
|
+
Rpush.config.push = true
|
15
6
|
Rpush::Daemon.common_init
|
16
7
|
Rpush::Daemon::Synchronizer.sync
|
17
8
|
Rpush::Daemon::Feeder.start(true) # non-blocking
|
@@ -6,7 +6,7 @@ module Rpush
|
|
6
6
|
:apns_feedback, :notification_enqueued, :notification_delivered,
|
7
7
|
:notification_failed, :notification_will_retry, :gcm_delivered_to_recipient,
|
8
8
|
:gcm_failed_to_recipient, :gcm_canonical_id, :gcm_invalid_registration_id,
|
9
|
-
:error, :adm_canonical_id, :adm_failed_to_recipient,
|
9
|
+
:error, :adm_canonical_id, :adm_failed_to_recipient, :wns_invalid_channel,
|
10
10
|
:tcp_connection_lost, :ssl_certificate_will_expire, :ssl_certificate_revoked,
|
11
11
|
:notification_id_will_retry, :notification_id_failed
|
12
12
|
]
|
@@ -17,30 +17,28 @@ module Rpush
|
|
17
17
|
class_eval(<<-RUBY, __FILE__, __LINE__)
|
18
18
|
def #{reflection}(*args, &blk)
|
19
19
|
raise "block required" unless block_given?
|
20
|
-
reflections[:#{reflection}] = blk
|
20
|
+
@reflections[:#{reflection}] = blk
|
21
21
|
end
|
22
22
|
RUBY
|
23
23
|
end
|
24
24
|
|
25
|
+
def initialize
|
26
|
+
@reflections = {}
|
27
|
+
end
|
28
|
+
|
25
29
|
def __dispatch(reflection, *args)
|
26
|
-
|
30
|
+
blk = @reflections[reflection]
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
32
|
+
if blk
|
33
|
+
blk.call(*args)
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
if DEPRECATIONS.key?(reflection)
|
36
|
+
replacement, removal_version = DEPRECATIONS[reflection]
|
37
|
+
Rpush::Deprecation.warn("#{reflection} is deprecated and will be removed in version #{removal_version}. Use #{replacement} instead.")
|
38
|
+
end
|
39
|
+
elsif !REFLECTIONS.include?(reflection)
|
40
|
+
raise NoSuchReflectionError, reflection
|
35
41
|
end
|
36
|
-
|
37
|
-
reflections[reflection].call(*args) if reflections[reflection]
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def reflections
|
43
|
-
@reflections ||= {}
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Rpush
|
2
|
-
|
3
|
-
|
2
|
+
@reflection_stack ||= [ReflectionCollection.new]
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_reader :reflection_stack
|
4
6
|
end
|
5
7
|
|
6
|
-
def self.
|
7
|
-
|
8
|
+
def self.reflect
|
9
|
+
yield reflection_stack[0] if block_given?
|
8
10
|
end
|
9
11
|
end
|
data/lib/rpush/version.rb
CHANGED
@@ -11,7 +11,7 @@ describe 'APNs' do
|
|
11
11
|
|
12
12
|
before do
|
13
13
|
Rpush.config.push_poll = 0.5
|
14
|
-
stub_tcp_connection
|
14
|
+
stub_tcp_connection(tcp_socket, ssl_socket, io_double)
|
15
15
|
end
|
16
16
|
|
17
17
|
def create_app
|
@@ -32,12 +32,6 @@ describe 'APNs' do
|
|
32
32
|
notification
|
33
33
|
end
|
34
34
|
|
35
|
-
def stub_tcp_connection
|
36
|
-
allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
|
37
|
-
allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
|
38
|
-
stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
|
39
|
-
end
|
40
|
-
|
41
35
|
def wait
|
42
36
|
sleep 0.1
|
43
37
|
end
|
@@ -71,10 +65,6 @@ describe 'APNs' do
|
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
74
|
-
def timeout(&blk)
|
75
|
-
Timeout.timeout(10, &blk)
|
76
|
-
end
|
77
|
-
|
78
68
|
it 'delivers a notification successfully' do
|
79
69
|
notification = create_notification
|
80
70
|
expect do
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'functional_spec_helper'
|
2
|
+
|
3
|
+
describe Rpush::CLI do
|
4
|
+
def create_app
|
5
|
+
app = Rpush::Apns::App.new
|
6
|
+
app.certificate = TEST_CERT
|
7
|
+
app.name = 'test'
|
8
|
+
app.environment = 'sandbox'
|
9
|
+
app.save!
|
10
|
+
app
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'status' do
|
14
|
+
let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
|
15
|
+
let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
|
16
|
+
let(:io_double) { double(select: nil) }
|
17
|
+
|
18
|
+
before do
|
19
|
+
create_app
|
20
|
+
stub_tcp_connection(tcp_socket, ssl_socket, io_double)
|
21
|
+
Rpush.embed
|
22
|
+
|
23
|
+
timeout do
|
24
|
+
Thread.pass until File.exist?(Rpush::Daemon::Rpc.socket_path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
after { timeout { Rpush.shutdown } }
|
29
|
+
|
30
|
+
it 'prints the status' do
|
31
|
+
expect(subject).to receive(:configure_rpush) { true }
|
32
|
+
expect(subject).to receive(:puts).with(/app_runners:/)
|
33
|
+
subject.status
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -4,7 +4,17 @@ require 'database_cleaner'
|
|
4
4
|
DatabaseCleaner.strategy = :truncation
|
5
5
|
|
6
6
|
def functional_example?(metadata)
|
7
|
-
metadata[:file_path] =~ /spec
|
7
|
+
metadata[:file_path] =~ %r{/spec/functional/}
|
8
|
+
end
|
9
|
+
|
10
|
+
def timeout(&blk)
|
11
|
+
Timeout.timeout(10, &blk)
|
12
|
+
end
|
13
|
+
|
14
|
+
def stub_tcp_connection(tcp_socket, ssl_socket, io_double)
|
15
|
+
allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
|
16
|
+
allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
|
17
|
+
stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
|
8
18
|
end
|
9
19
|
|
10
20
|
RSpec.configure do |config|
|
data/spec/spec_helper.rb
CHANGED
@@ -3,9 +3,6 @@ def client
|
|
3
3
|
(ENV['CLIENT'] || :active_record).to_sym
|
4
4
|
end
|
5
5
|
|
6
|
-
require 'bundler/setup'
|
7
|
-
Bundler.require(:default)
|
8
|
-
|
9
6
|
if !ENV['TRAVIS'] || (ENV['TRAVIS'] && ENV['QUALITY'] == 'true')
|
10
7
|
begin
|
11
8
|
require './spec/support/simplecov_helper'
|
@@ -16,6 +13,9 @@ if !ENV['TRAVIS'] || (ENV['TRAVIS'] && ENV['QUALITY'] == 'true')
|
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
16
|
+
require 'timecop'
|
17
|
+
require 'activerecord-jdbc-adapter' if defined? JRUBY_VERSION
|
18
|
+
|
19
19
|
require 'rpush'
|
20
20
|
require 'rpush/daemon'
|
21
21
|
require 'rpush/client/redis'
|
@@ -42,6 +42,7 @@ RPUSH_ROOT = '/tmp/rails_root'
|
|
42
42
|
|
43
43
|
Rpush.configure do |config|
|
44
44
|
config.client = client
|
45
|
+
config.log_level = ::Logger::Severity::DEBUG
|
45
46
|
end
|
46
47
|
|
47
48
|
RPUSH_CLIENT = Rpush.config.client
|
@@ -29,11 +29,12 @@ ActiveRecord::Base.establish_connection(db_config[SPEC_ADAPTER])
|
|
29
29
|
require 'generators/templates/add_rpush'
|
30
30
|
require 'generators/templates/rpush_2_0_0_updates'
|
31
31
|
require 'generators/templates/rpush_2_1_0_updates'
|
32
|
+
require 'generators/templates/rpush_2_6_0_updates'
|
32
33
|
|
33
|
-
migrations = [AddRpush, Rpush200Updates, Rpush210Updates]
|
34
|
+
migrations = [AddRpush, Rpush200Updates, Rpush210Updates, Rpush260Updates]
|
34
35
|
|
35
36
|
unless ENV['TRAVIS']
|
36
|
-
migrations.
|
37
|
+
migrations.reverse_each do |m|
|
37
38
|
begin
|
38
39
|
m.down
|
39
40
|
rescue ActiveRecord::StatementInvalid => e
|
@@ -217,7 +217,7 @@ describe Rpush::Client::ActiveRecord::Apns::Notification, "bug #31" do
|
|
217
217
|
|
218
218
|
it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
|
219
219
|
notification = Rpush::Client::ActiveRecord::Apns::Notification.new
|
220
|
-
allow(notification).to receive_messages(
|
220
|
+
allow(notification).to receive_messages(has_attribute?: false)
|
221
221
|
notification.alert = "{\"one\":2}"
|
222
222
|
expect(notification.alert).to eq('one' => 2)
|
223
223
|
end
|
@@ -31,4 +31,9 @@ describe Rpush::Client::ActiveRecord::Gcm::Notification do
|
|
31
31
|
notification.expiry = 100
|
32
32
|
expect(notification.as_json['time_to_live']).to eq 100
|
33
33
|
end
|
34
|
+
|
35
|
+
it 'includes content_available in the payload' do
|
36
|
+
notification.content_available = true
|
37
|
+
expect(notification.as_json['content_available']).to eq true
|
38
|
+
end
|
34
39
|
end if active_record?
|
@@ -43,11 +43,4 @@ describe Rpush::Configuration do
|
|
43
43
|
Rpush.config.redis_options = { hi: :mom }
|
44
44
|
expect(Modis.redis_options).to eq(hi: :mom)
|
45
45
|
end
|
46
|
-
|
47
|
-
it 'deprecates feedback_poll=' do
|
48
|
-
expect(Rpush::Deprecation).to receive(:warn).with(/feedback_poll= is deprecated/)
|
49
|
-
expect do
|
50
|
-
Rpush.config.feedback_poll = 123
|
51
|
-
end.to change { Rpush.config.apns.feedback_receiver.frequency }.to(123)
|
52
|
-
end
|
53
46
|
end
|
@@ -78,14 +78,14 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
78
78
|
it 'logs that the notification was not delivered' do
|
79
79
|
allow(response).to receive_messages(body: JSON.dump('reason' => 'InvalidRegistrationId'))
|
80
80
|
expect(logger).to receive(:warn).with("[MyApp] bad_request: xyz (InvalidRegistrationId)")
|
81
|
-
expect { perform }.to raise_error
|
81
|
+
expect { perform }.to raise_error(Rpush::DeliveryError)
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'reflects' do
|
85
85
|
allow(response).to receive_messages(body: JSON.dump('registrationID' => 'canonical123', 'reason' => 'Unregistered'))
|
86
86
|
allow(notification).to receive_messages(registration_ids: ['1'])
|
87
87
|
expect(delivery).to receive(:reflect).with(:adm_failed_to_recipient, notification, '1', 'Unregistered')
|
88
|
-
expect { perform }.to raise_error
|
88
|
+
expect { perform }.to raise_error(Rpush::DeliveryError)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -94,9 +94,8 @@ describe Rpush::Daemon::AppRunner, 'debug' do
|
|
94
94
|
|
95
95
|
after { Rpush::Daemon::AppRunner.stop_app(app.id) }
|
96
96
|
|
97
|
-
it '
|
98
|
-
expect(Rpush.
|
99
|
-
Rpush::Daemon::AppRunner.debug
|
97
|
+
it 'returns the app runner status' do
|
98
|
+
expect(Rpush::Daemon::AppRunner.status.key?(:app_runners)).to eq(true)
|
100
99
|
end
|
101
100
|
end
|
102
101
|
|
@@ -126,7 +126,7 @@ describe Rpush::Daemon::TcpConnection do
|
|
126
126
|
end
|
127
127
|
|
128
128
|
it 'logs that the certificate has been revoked' do
|
129
|
-
expect(logger).to receive(:
|
129
|
+
expect(logger).to receive(:error).with('[Connection 0] Certificate has been revoked.')
|
130
130
|
expect { connection.connect }.to raise_error(Rpush::Daemon::TcpConnectionError, 'OpenSSL::SSL::SSLError, certificate revoked')
|
131
131
|
end
|
132
132
|
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe Rpush::Daemon::Wns::Delivery do
|
4
|
+
let(:app) { Rpush::Wns::App.create!(name: "MyApp", client_id: "someclient", client_secret: "somesecret", access_token: "access_token", access_token_expiration: Time.now + (60 * 10)) }
|
5
|
+
let(:notification) { Rpush::Wns::Notification.create!(app: app, data: { title: "MyApp", body: "Example notification", param: "/param1" }, uri: "http://some.example/", deliver_after: Time.now) }
|
6
|
+
let(:logger) { double(error: nil, info: nil, warn: nil) }
|
7
|
+
let(:response) { double(code: 200, header: {}, body: '') }
|
8
|
+
let(:http) { double(shutdown: nil, request: response) }
|
9
|
+
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
10
|
+
let(:batch) { double(mark_failed: nil, mark_delivered: nil, mark_retryable: nil, notification_processed: nil) }
|
11
|
+
let(:delivery) { Rpush::Daemon::Wns::Delivery.new(app, http, notification, batch) }
|
12
|
+
let(:store) { double(create_wpns_notification: double(id: 2), update_app: nil) }
|
13
|
+
|
14
|
+
def perform
|
15
|
+
delivery.perform
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform_with_rescue
|
19
|
+
expect { perform }.to raise_error(StandardError)
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
allow(delivery).to receive_messages(reflect: nil)
|
24
|
+
allow(Rpush::Daemon).to receive_messages(store: store)
|
25
|
+
allow(Time).to receive_messages(now: now)
|
26
|
+
allow(Rpush).to receive_messages(logger: logger)
|
27
|
+
end
|
28
|
+
|
29
|
+
shared_examples_for "an notification with some delivery faliures" do
|
30
|
+
let(:new_notification) { Rpush::Wns::Notification.where('id != ?', notification.id).first }
|
31
|
+
|
32
|
+
before { allow(response).to receive_messages(body: JSON.dump(body)) }
|
33
|
+
|
34
|
+
it "marks the original notification falied" do
|
35
|
+
expect(delivery).to receive(:mark_failed) do |error|
|
36
|
+
expect(error.message).to match(error_description)
|
37
|
+
end
|
38
|
+
perform_with_rescue
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises a DeliveryError" do
|
42
|
+
expect { perform }.to raise_error(Rpush::DeliveryError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "an 200 response without an access token" do
|
47
|
+
before do
|
48
|
+
allow(app).to receive_messages(access_token_expired?: true)
|
49
|
+
allow(response).to receive_messages(to_hash: {}, code: 200, body: JSON.dump(access_token: "dummy_access_token", expires_in: 60))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'set the access token for the app' do
|
53
|
+
expect(delivery).to receive(:update_access_token).with("access_token" => "dummy_access_token", "expires_in" => 60)
|
54
|
+
expect(store).to receive(:update_app).with app
|
55
|
+
perform
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "an 200 response with a valid access token" do
|
60
|
+
before do
|
61
|
+
allow(response).to receive_messages(code: 200)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "marks the notification as delivered if delivered successfully to all devices" do
|
65
|
+
allow(response).to receive_messages(body: JSON.dump("failure" => 0))
|
66
|
+
allow(response).to receive_messages(to_hash: { "X-WNS-Status" => ["received"] })
|
67
|
+
expect(batch).to receive(:mark_delivered).with(notification)
|
68
|
+
perform
|
69
|
+
end
|
70
|
+
|
71
|
+
it "retries the notification when the queue is full" do
|
72
|
+
allow(response).to receive_messages(body: JSON.dump("failure" => 0))
|
73
|
+
allow(response).to receive_messages(to_hash: { "X-WNS-Status" => ["channelthrottled"] })
|
74
|
+
expect(batch).to receive(:mark_retryable).with(notification, Time.now + (60 * 10))
|
75
|
+
perform
|
76
|
+
end
|
77
|
+
|
78
|
+
it "marks the notification as failed if the notification is suppressed" do
|
79
|
+
allow(response).to receive_messages(body: JSON.dump("faliure" => 0))
|
80
|
+
allow(response).to receive_messages(to_hash: { "X-WNS-Status" => ["dropped"], "X-WNS-Error-Description" => "" })
|
81
|
+
error = Rpush::DeliveryError.new(200, notification.id, 'Notification was received but suppressed by the service ().')
|
82
|
+
expect(delivery).to receive(:mark_failed).with(error)
|
83
|
+
perform_with_rescue
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "an 400 response" do
|
88
|
+
before { allow(response).to receive_messages(code: 400) }
|
89
|
+
it "marks notifications as failed" do
|
90
|
+
error = Rpush::DeliveryError.new(400, notification.id, 'One or more headers were specified incorrectly or conflict with another header.')
|
91
|
+
expect(delivery).to receive(:mark_failed).with(error)
|
92
|
+
perform_with_rescue
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "an 404 response" do
|
97
|
+
before { allow(response).to receive_messages(code: 404) }
|
98
|
+
it "marks notifications as failed" do
|
99
|
+
error = Rpush::DeliveryError.new(404, notification.id, 'The channel URI is not valid or is not recognized by WNS.')
|
100
|
+
expect(delivery).to receive(:mark_failed).with(error)
|
101
|
+
perform_with_rescue
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "an 405 response" do
|
106
|
+
before { allow(response).to receive_messages(code: 405) }
|
107
|
+
it "marks notifications as failed" do
|
108
|
+
error = Rpush::DeliveryError.new(405, notification.id, 'Invalid method (GET, CREATE); only POST (Windows or Windows Phone) or DELETE (Windows Phone only) is allowed.')
|
109
|
+
expect(delivery).to receive(:mark_failed).with(error)
|
110
|
+
perform_with_rescue
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "an 406 response" do
|
115
|
+
before { allow(response).to receive_messages(code: 406) }
|
116
|
+
|
117
|
+
it "retries the notification" do
|
118
|
+
expect(batch).to receive(:mark_retryable).with(notification, Time.now + (60 * 60))
|
119
|
+
perform
|
120
|
+
end
|
121
|
+
|
122
|
+
it "logs a warning that the notification will be retried" do
|
123
|
+
notification.retries = 1
|
124
|
+
notification.deliver_after = now + 2
|
125
|
+
expect(logger).to receive(:warn).with("[MyApp] Per-day throttling limit reached. Notification #{notification.id} will be retried after 2012-10-14 00:00:02 (retry 1).")
|
126
|
+
perform
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "an 412 response" do
|
131
|
+
before { allow(response).to receive_messages(code: 412) }
|
132
|
+
|
133
|
+
it "retries the notification" do
|
134
|
+
expect(batch).to receive(:mark_retryable).with(notification, Time.now + (60 * 60))
|
135
|
+
perform
|
136
|
+
end
|
137
|
+
|
138
|
+
it "logs a warning that the notification will be retried" do
|
139
|
+
notification.retries = 1
|
140
|
+
notification.deliver_after = now + 2
|
141
|
+
expect(logger).to receive(:warn).with("[MyApp] Device unreachable. Notification #{notification.id} will be retried after 2012-10-14 00:00:02 (retry 1).")
|
142
|
+
perform
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "an 503 response" do
|
147
|
+
before { allow(response).to receive_messages(code: 503) }
|
148
|
+
|
149
|
+
it "retries the notification exponentially" do
|
150
|
+
expect(delivery).to receive(:mark_retryable_exponential).with(notification)
|
151
|
+
perform
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'logs a warning that the notification will be retried.' do
|
155
|
+
notification.retries = 1
|
156
|
+
notification.deliver_after = now + 2
|
157
|
+
expect(logger).to receive(:warn).with("[MyApp] Service Unavailable. Notification #{notification.id} will be retried after 2012-10-14 00:00:02 (retry 1).")
|
158
|
+
perform
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'an un-handled response' do
|
163
|
+
before { allow(response).to receive_messages(code: 418) }
|
164
|
+
|
165
|
+
it 'marks the notification as failed' do
|
166
|
+
error = Rpush::DeliveryError.new(418, notification.id, "I'm a Teapot")
|
167
|
+
expect(delivery).to receive(:mark_failed).with(error)
|
168
|
+
perform_with_rescue
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|