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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -1
  3. data/README.md +18 -8
  4. data/lib/generators/rpush_migration_generator.rb +1 -0
  5. data/lib/generators/templates/rpush.rb +8 -2
  6. data/lib/generators/templates/rpush_2_0_0_updates.rb +1 -1
  7. data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
  8. data/lib/rpush/cli.rb +63 -27
  9. data/lib/rpush/client/active_model.rb +3 -0
  10. data/lib/rpush/client/active_model/apns/notification.rb +1 -1
  11. data/lib/rpush/client/active_model/gcm/notification.rb +1 -0
  12. data/lib/rpush/client/active_model/wns/app.rb +23 -0
  13. data/lib/rpush/client/active_model/wns/notification.rb +28 -0
  14. data/lib/rpush/client/active_model/wpns/notification.rb +11 -6
  15. data/lib/rpush/client/active_record.rb +3 -0
  16. data/lib/rpush/client/active_record/notification.rb +1 -1
  17. data/lib/rpush/client/active_record/wns/app.rb +11 -0
  18. data/lib/rpush/client/active_record/wns/notification.rb +11 -0
  19. data/lib/rpush/client/mongoid.rb +3 -0
  20. data/lib/rpush/client/mongoid/apns/feedback.rb +3 -0
  21. data/lib/rpush/client/mongoid/notification.rb +7 -0
  22. data/lib/rpush/client/mongoid/wns/app.rb +14 -0
  23. data/lib/rpush/client/mongoid/wns/notification.rb +11 -0
  24. data/lib/rpush/client/redis.rb +3 -0
  25. data/lib/rpush/client/redis/notification.rb +1 -0
  26. data/lib/rpush/client/redis/wns/app.rb +14 -0
  27. data/lib/rpush/client/redis/wns/notification.rb +11 -0
  28. data/lib/rpush/configuration.rb +3 -7
  29. data/lib/rpush/daemon.rb +9 -0
  30. data/lib/rpush/daemon/apns/feedback_receiver.rb +5 -0
  31. data/lib/rpush/daemon/app_runner.rb +4 -5
  32. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +47 -12
  33. data/lib/rpush/daemon/dispatcher_loop.rb +5 -0
  34. data/lib/rpush/daemon/feeder.rb +11 -0
  35. data/lib/rpush/daemon/gcm/delivery.rb +2 -2
  36. data/lib/rpush/daemon/interruptible_sleep.rb +8 -3
  37. data/lib/rpush/daemon/loggable.rb +4 -0
  38. data/lib/rpush/daemon/rpc.rb +9 -0
  39. data/lib/rpush/daemon/rpc/client.rb +27 -0
  40. data/lib/rpush/daemon/rpc/server.rb +82 -0
  41. data/lib/rpush/daemon/signal_handler.rb +7 -0
  42. data/lib/rpush/daemon/store/active_record.rb +17 -3
  43. data/lib/rpush/daemon/store/mongoid.rb +2 -2
  44. data/lib/rpush/daemon/store/redis.rb +2 -2
  45. data/lib/rpush/daemon/tcp_connection.rb +2 -2
  46. data/lib/rpush/daemon/wns.rb +9 -0
  47. data/lib/rpush/daemon/wns/delivery.rb +204 -0
  48. data/lib/rpush/embed.rb +15 -13
  49. data/lib/rpush/logger.rb +4 -0
  50. data/lib/rpush/plugin.rb +1 -1
  51. data/lib/rpush/push.rb +2 -11
  52. data/lib/rpush/reflection_collection.rb +15 -17
  53. data/lib/rpush/reflection_public_methods.rb +6 -4
  54. data/lib/rpush/version.rb +1 -1
  55. data/spec/functional/apns_spec.rb +1 -11
  56. data/spec/functional/cli_spec.rb +36 -0
  57. data/spec/functional_spec_helper.rb +11 -1
  58. data/spec/spec_helper.rb +4 -3
  59. data/spec/support/active_record_setup.rb +3 -2
  60. data/spec/unit/client/active_record/apns/notification_spec.rb +1 -1
  61. data/spec/unit/client/active_record/gcm/notification_spec.rb +5 -0
  62. data/spec/unit/configuration_spec.rb +0 -7
  63. data/spec/unit/daemon/adm/delivery_spec.rb +2 -2
  64. data/spec/unit/daemon/app_runner_spec.rb +2 -3
  65. data/spec/unit/daemon/gcm/delivery_spec.rb +1 -1
  66. data/spec/unit/daemon/tcp_connection_spec.rb +1 -1
  67. data/spec/unit/daemon/wns/delivery_spec.rb +171 -0
  68. data/spec/unit/daemon/wpns/delivery_spec.rb +1 -1
  69. data/spec/unit/daemon_spec.rb +2 -0
  70. data/spec/unit/embed_spec.rb +4 -11
  71. data/spec/unit/logger_spec.rb +2 -2
  72. data/spec/unit/push_spec.rb +0 -7
  73. data/spec/unit_spec_helper.rb +1 -1
  74. metadata +20 -2
@@ -1,21 +1,13 @@
1
1
  module Rpush
2
- def self.embed(options = {})
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 = Rpush::ConfigurationWithoutDefaults.new
15
- options.each { |k, v| config.send("#{k}=", v) }
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.debug
31
+ def self.status
36
32
  return unless Rpush.config.embedded
37
- Rpush::Daemon::AppRunner.debug
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
@@ -11,6 +11,10 @@ module Rpush
11
11
  error('Logging disabled.')
12
12
  end
13
13
 
14
+ def debug(msg, inline = false)
15
+ log(:debug, msg, inline)
16
+ end
17
+
14
18
  def info(msg, inline = false)
15
19
  log(:info, msg, inline)
16
20
  end
@@ -32,7 +32,7 @@ module Rpush
32
32
  Rpush.config.plugin.send("#{@name}=", @config)
33
33
  end
34
34
 
35
- def init(&block) # rubocop:disable Style/TrivialAccessors
35
+ def init(&block)
36
36
  @init_block = block
37
37
  end
38
38
 
@@ -1,17 +1,8 @@
1
1
  module Rpush
2
- def self.push(options = {})
2
+ def self.push
3
3
  require 'rpush/daemon'
4
4
 
5
- unless options.empty?
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
- reflection = reflection.to_sym
30
+ blk = @reflections[reflection]
27
31
 
28
- unless REFLECTIONS.include?(reflection)
29
- fail NoSuchReflectionError, reflection
30
- end
32
+ if blk
33
+ blk.call(*args)
31
34
 
32
- if DEPRECATIONS.key?(reflection)
33
- replacement, removal_version = DEPRECATIONS[reflection]
34
- Rpush::Deprecation.warn("#{reflection} is deprecated and will be removed in version #{removal_version}. Use #{replacement} instead.")
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
- def self.reflect
3
- yield reflection_stack[0] if block_given?
2
+ @reflection_stack ||= [ReflectionCollection.new]
3
+
4
+ class << self
5
+ attr_reader :reflection_stack
4
6
  end
5
7
 
6
- def self.reflection_stack
7
- @reflection_stack ||= [ReflectionCollection.new]
8
+ def self.reflect
9
+ yield reflection_stack[0] if block_given?
8
10
  end
9
11
  end
@@ -1,3 +1,3 @@
1
1
  module Rpush
2
- VERSION = '2.4.0'
2
+ VERSION = '2.6.0'
3
3
  end
@@ -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\/functional/
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|
@@ -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.reverse.each do |m|
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(:has_attribute? => false)
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 'prints debug app states to the log' do
98
- expect(Rpush.logger).to receive(:info).with(kind_of(String))
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
 
@@ -16,7 +16,7 @@ describe Rpush::Daemon::Gcm::Delivery do
16
16
  end
17
17
 
18
18
  def perform_with_rescue
19
- expect { perform }.to raise_error
19
+ expect { perform }.to raise_error(StandardError)
20
20
  end
21
21
 
22
22
  before do
@@ -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(:warn).with('[Connection 0] Certificate has been revoked.')
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