rpush 5.0.0 → 6.0.0
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 +74 -2
- data/README.md +104 -18
- data/lib/generators/templates/add_adm.rb +1 -1
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +2 -2
- 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 +11 -25
- data/lib/generators/templates/add_rpush.rb +33 -83
- data/lib/generators/templates/add_wpns.rb +1 -1
- data/lib/generators/templates/create_rapns_apps.rb +1 -1
- data/lib/generators/templates/create_rapns_feedback.rb +3 -9
- data/lib/generators/templates/create_rapns_notifications.rb +3 -9
- data/lib/generators/templates/rename_rapns_to_rpush.rb +9 -33
- data/lib/generators/templates/rpush.rb +4 -0
- data/lib/generators/templates/rpush_2_0_0_updates.rb +5 -17
- data/lib/generators/templates/rpush_2_1_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_6_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_7_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_0_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_0_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +1 -1
- data/lib/generators/templates/rpush_3_1_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +1 -1
- data/lib/generators/templates/rpush_3_2_4_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_3_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_3_1_updates.rb +3 -3
- data/lib/generators/templates/rpush_4_1_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_4_1_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_4_2_0_updates.rb +1 -1
- data/lib/rpush/cli.rb +1 -1
- data/lib/rpush/client/active_model.rb +5 -1
- data/lib/rpush/client/active_model/adm/data_validator.rb +1 -1
- data/lib/rpush/client/active_model/apns/app.rb +1 -17
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +2 -2
- data/lib/rpush/client/active_model/apns/notification.rb +13 -1
- data/lib/rpush/client/active_model/apns/notification_payload_size_validator.rb +15 -0
- data/lib/rpush/client/active_model/apns2/app.rb +7 -1
- data/lib/rpush/client/active_model/apns2/notification.rb +14 -0
- data/lib/rpush/client/active_model/certificate_private_key_validator.rb +19 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +1 -1
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +1 -1
- data/lib/rpush/client/active_model/webpush/app.rb +41 -0
- data/lib/rpush/client/active_model/webpush/notification.rb +66 -0
- data/lib/rpush/client/active_record.rb +4 -0
- data/lib/rpush/client/active_record/apns/active_record_serializable_notification.rb +65 -0
- data/lib/rpush/client/active_record/apns/notification.rb +1 -57
- data/lib/rpush/client/active_record/apns2/notification.rb +4 -1
- data/lib/rpush/client/active_record/apnsp8/notification.rb +1 -0
- data/lib/rpush/client/active_record/webpush/app.rb +11 -0
- data/lib/rpush/client/active_record/webpush/notification.rb +12 -0
- data/lib/rpush/client/redis.rb +3 -0
- data/lib/rpush/client/redis/apns2/notification.rb +1 -0
- data/lib/rpush/client/redis/apnsp8/notification.rb +2 -0
- data/lib/rpush/client/redis/pushy/notification.rb +0 -1
- data/lib/rpush/client/redis/webpush/app.rb +15 -0
- data/lib/rpush/client/redis/webpush/notification.rb +15 -0
- data/lib/rpush/configuration.rb +3 -2
- data/lib/rpush/daemon.rb +4 -1
- data/lib/rpush/daemon/apns/feedback_receiver.rb +1 -1
- data/lib/rpush/daemon/apns2/delivery.rb +14 -2
- data/lib/rpush/daemon/apnsp8/delivery.rb +14 -3
- data/lib/rpush/daemon/app_runner.rb +1 -1
- data/lib/rpush/daemon/batch.rb +12 -5
- data/lib/rpush/daemon/delivery.rb +1 -2
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +1 -1
- data/lib/rpush/daemon/string_helpers.rb +1 -1
- data/lib/rpush/daemon/webpush.rb +10 -0
- data/lib/rpush/daemon/webpush/delivery.rb +114 -0
- data/lib/rpush/logger.rb +1 -0
- data/lib/rpush/version.rb +1 -1
- data/spec/functional/apns2_spec.rb +99 -2
- data/spec/functional/retry_spec.rb +1 -1
- data/spec/functional/webpush_spec.rb +30 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/active_record_setup.rb +4 -3
- data/spec/support/config/database.yml +4 -4
- data/spec/support/simplecov_helper.rb +2 -2
- data/spec/unit/client/active_record/adm/app_spec.rb +2 -54
- data/spec/unit/client/active_record/adm/notification_spec.rb +2 -39
- data/spec/unit/client/active_record/apns/app_spec.rb +3 -26
- data/spec/unit/client/active_record/apns/feedback_spec.rb +1 -5
- data/spec/unit/client/active_record/apns/notification_spec.rb +29 -293
- data/spec/unit/client/active_record/apns2/app_spec.rb +5 -0
- data/spec/unit/client/active_record/apns2/notification_spec.rb +65 -0
- data/spec/unit/client/active_record/apnsp8/notification_spec.rb +28 -0
- data/spec/unit/client/active_record/app_spec.rb +1 -26
- data/spec/unit/client/active_record/gcm/app_spec.rb +3 -1
- data/spec/unit/client/active_record/gcm/notification_spec.rb +6 -88
- data/spec/unit/client/active_record/notification_spec.rb +3 -11
- data/spec/unit/client/active_record/pushy/app_spec.rb +2 -13
- data/spec/unit/client/active_record/pushy/notification_spec.rb +2 -55
- data/spec/unit/client/active_record/shared/app.rb +14 -0
- data/spec/unit/{notification_shared.rb → client/active_record/shared/notification.rb} +12 -7
- data/spec/unit/client/active_record/webpush/app_spec.rb +6 -0
- data/spec/unit/client/active_record/webpush/notification_spec.rb +6 -0
- data/spec/unit/client/active_record/wns/badge_notification_spec.rb +1 -11
- data/spec/unit/client/active_record/wns/raw_notification_spec.rb +3 -12
- data/spec/unit/client/active_record/wpns/app_spec.rb +3 -1
- data/spec/unit/client/active_record/wpns/notification_spec.rb +2 -17
- data/spec/unit/client/redis/adm/app_spec.rb +5 -0
- data/spec/unit/client/redis/adm/notification_spec.rb +5 -0
- data/spec/unit/client/redis/apns/app_spec.rb +5 -0
- data/spec/unit/client/redis/apns/feedback_spec.rb +5 -0
- data/spec/unit/client/redis/apns/notification_spec.rb +50 -0
- data/spec/unit/client/redis/apns2/app_spec.rb +4 -0
- data/spec/unit/client/redis/apns2/notification_spec.rb +50 -0
- data/spec/unit/client/redis/apnsp8/notification_spec.rb +29 -0
- data/spec/unit/client/redis/app_spec.rb +5 -0
- data/spec/unit/client/redis/gcm/app_spec.rb +5 -0
- data/spec/unit/client/redis/gcm/notification_spec.rb +5 -0
- data/spec/unit/client/redis/notification_spec.rb +5 -0
- data/spec/unit/client/redis/pushy/app_spec.rb +5 -0
- data/spec/unit/client/redis/pushy/notification_spec.rb +5 -0
- data/spec/unit/client/redis/webpush/app_spec.rb +5 -0
- data/spec/unit/client/redis/webpush/notification_spec.rb +5 -0
- data/spec/unit/client/redis/wns/badge_notification_spec.rb +5 -0
- data/spec/unit/client/redis/wns/raw_notification_spec.rb +22 -0
- data/spec/unit/client/redis/wpns/app_spec.rb +5 -0
- data/spec/unit/client/redis/wpns/notification_spec.rb +5 -0
- data/spec/unit/client/shared/adm/app.rb +51 -0
- data/spec/unit/client/shared/adm/notification.rb +39 -0
- data/spec/unit/client/shared/apns/app.rb +29 -0
- data/spec/unit/client/shared/apns/feedback.rb +9 -0
- data/spec/unit/client/shared/apns/notification.rb +277 -0
- data/spec/unit/client/shared/app.rb +17 -0
- data/spec/unit/client/shared/gcm/app.rb +4 -0
- data/spec/unit/client/shared/gcm/notification.rb +77 -0
- data/spec/unit/client/shared/notification.rb +10 -0
- data/spec/unit/client/shared/pushy/app.rb +17 -0
- data/spec/unit/client/shared/pushy/notification.rb +55 -0
- data/spec/unit/client/shared/webpush/app.rb +33 -0
- data/spec/unit/client/shared/webpush/notification.rb +83 -0
- data/spec/unit/client/shared/wns/badge_notification.rb +15 -0
- data/spec/unit/client/shared/wns/raw_notification.rb +21 -0
- data/spec/unit/client/shared/wpns/app.rb +4 -0
- data/spec/unit/client/shared/wpns/notification.rb +18 -0
- data/spec/unit/daemon/apnsp8/delivery_spec.rb +53 -0
- data/spec/unit/daemon/batch_spec.rb +50 -2
- data/spec/unit/daemon/delivery_spec.rb +10 -0
- data/spec/unit/daemon/pushy/delivery_spec.rb +5 -3
- data/spec/unit/daemon/shared/store.rb +312 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +7 -7
- data/spec/unit/daemon/store/active_record_spec.rb +2 -290
- data/spec/unit/daemon/store/redis_spec.rb +2 -291
- data/spec/unit/daemon/webpush/delivery_spec.rb +144 -0
- data/spec/unit_spec_helper.rb +3 -0
- metadata +137 -13
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +0 -16
data/lib/rpush/daemon.rb
CHANGED
|
@@ -68,6 +68,9 @@ require 'rpush/daemon/adm'
|
|
|
68
68
|
require 'rpush/daemon/pushy'
|
|
69
69
|
require 'rpush/daemon/pushy/delivery'
|
|
70
70
|
|
|
71
|
+
require 'rpush/daemon/webpush/delivery'
|
|
72
|
+
require 'rpush/daemon/webpush'
|
|
73
|
+
|
|
71
74
|
module Rpush
|
|
72
75
|
module Daemon
|
|
73
76
|
class << self
|
|
@@ -109,7 +112,7 @@ module Rpush
|
|
|
109
112
|
Feeder.stop
|
|
110
113
|
AppRunner.stop
|
|
111
114
|
delete_pid_file
|
|
112
|
-
puts Rainbow('✔').red if Rpush.config.foreground
|
|
115
|
+
puts Rainbow('✔').red if Rpush.config.foreground && Rpush.config.foreground_logging
|
|
113
116
|
end
|
|
114
117
|
end
|
|
115
118
|
|
|
@@ -7,6 +7,7 @@ module Rpush
|
|
|
7
7
|
|
|
8
8
|
class Delivery < Rpush::Daemon::Delivery
|
|
9
9
|
RETRYABLE_CODES = [ 429, 500, 503 ]
|
|
10
|
+
CLIENT_JOIN_TIMEOUT = 60
|
|
10
11
|
|
|
11
12
|
def initialize(app, http2_client, batch)
|
|
12
13
|
@app = app
|
|
@@ -20,7 +21,11 @@ module Rpush
|
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
# Send all preprocessed requests at once
|
|
23
|
-
@client.join
|
|
24
|
+
@client.join(timeout: CLIENT_JOIN_TIMEOUT)
|
|
25
|
+
rescue NetHttp2::AsyncRequestTimeout => error
|
|
26
|
+
mark_batch_retryable(Time.now + 10.seconds, error)
|
|
27
|
+
@client.close
|
|
28
|
+
raise
|
|
24
29
|
rescue Errno::ECONNREFUSED, SocketError => error
|
|
25
30
|
mark_batch_retryable(Time.now + 10.seconds, error)
|
|
26
31
|
raise
|
|
@@ -102,7 +107,14 @@ module Rpush
|
|
|
102
107
|
end
|
|
103
108
|
|
|
104
109
|
def prepare_headers(notification)
|
|
105
|
-
|
|
110
|
+
headers = {}
|
|
111
|
+
|
|
112
|
+
headers['apns-expiration'] = '0'
|
|
113
|
+
headers['apns-priority'] = '10'
|
|
114
|
+
headers['apns-topic'] = @app.bundle_id
|
|
115
|
+
headers['apns-push-type'] = 'background' if notification.content_available?
|
|
116
|
+
|
|
117
|
+
headers.merge notification_data(notification)[HTTP2_HEADERS_KEY] || {}
|
|
106
118
|
end
|
|
107
119
|
|
|
108
120
|
def notification_data(notification)
|
|
@@ -7,6 +7,8 @@ module Rpush
|
|
|
7
7
|
|
|
8
8
|
class Delivery < Rpush::Daemon::Delivery
|
|
9
9
|
RETRYABLE_CODES = [ 429, 500, 503 ]
|
|
10
|
+
CLIENT_JOIN_TIMEOUT = 60
|
|
11
|
+
DEFAULT_MAX_CONCURRENT_STREAMS = 100
|
|
10
12
|
|
|
11
13
|
def initialize(app, http2_client, token_provider, batch)
|
|
12
14
|
@app = app
|
|
@@ -22,7 +24,11 @@ module Rpush
|
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
# Send all preprocessed requests at once
|
|
25
|
-
@client.join
|
|
27
|
+
@client.join(timeout: CLIENT_JOIN_TIMEOUT)
|
|
28
|
+
rescue NetHttp2::AsyncRequestTimeout => error
|
|
29
|
+
mark_batch_retryable(Time.now + 10.seconds, error)
|
|
30
|
+
@client.close
|
|
31
|
+
raise
|
|
26
32
|
rescue Errno::ECONNREFUSED, SocketError, HTTP2::Error::StreamLimitExceeded => error
|
|
27
33
|
# TODO restart connection when StreamLimitExceeded
|
|
28
34
|
mark_batch_retryable(Time.now + 10.seconds, error)
|
|
@@ -80,7 +86,11 @@ module Rpush
|
|
|
80
86
|
def remote_max_concurrent_streams
|
|
81
87
|
# 0x7fffffff is the default value from http-2 gem (2^31)
|
|
82
88
|
if @client.remote_settings[:settings_max_concurrent_streams] == 0x7fffffff
|
|
83
|
-
|
|
89
|
+
# Ideally we'd fall back to `#local_settings` here, but `NetHttp2::Client`
|
|
90
|
+
# doesn't expose that attr from the `HTTP2::Client` it wraps. Instead, we
|
|
91
|
+
# chose a hard-coded value matching the default local setting from the
|
|
92
|
+
# `HTTP2::Client` class
|
|
93
|
+
DEFAULT_MAX_CONCURRENT_STREAMS
|
|
84
94
|
else
|
|
85
95
|
@client.remote_settings[:settings_max_concurrent_streams]
|
|
86
96
|
end
|
|
@@ -133,12 +143,13 @@ module Rpush
|
|
|
133
143
|
jwt_token = @token_provider.token
|
|
134
144
|
|
|
135
145
|
headers = {}
|
|
136
|
-
|
|
146
|
+
|
|
137
147
|
headers['content-type'] = 'application/json'
|
|
138
148
|
headers['apns-expiration'] = '0'
|
|
139
149
|
headers['apns-priority'] = '10'
|
|
140
150
|
headers['apns-topic'] = @app.bundle_id
|
|
141
151
|
headers['authorization'] = "bearer #{jwt_token}"
|
|
152
|
+
headers['apns-push-type'] = 'background' if notification.content_available?
|
|
142
153
|
|
|
143
154
|
headers.merge notification_data(notification)[HTTP2_HEADERS_KEY] || {}
|
|
144
155
|
end
|
|
@@ -29,7 +29,7 @@ module Rpush
|
|
|
29
29
|
Rpush.logger.info("[#{app.name}] Starting #{pluralize(app.connections, 'dispatcher')}... ", true)
|
|
30
30
|
runner = @runners[app.id] = new(app)
|
|
31
31
|
runner.start_dispatchers
|
|
32
|
-
puts Rainbow('✔').green if Rpush.config.foreground
|
|
32
|
+
puts Rainbow('✔').green if Rpush.config.foreground && Rpush.config.foreground_logging
|
|
33
33
|
runner.start_loops
|
|
34
34
|
rescue StandardError => e
|
|
35
35
|
@runners.delete(app.id)
|
data/lib/rpush/daemon/batch.rb
CHANGED
|
@@ -2,6 +2,7 @@ module Rpush
|
|
|
2
2
|
module Daemon
|
|
3
3
|
class Batch
|
|
4
4
|
include Reflectable
|
|
5
|
+
include Loggable
|
|
5
6
|
|
|
6
7
|
attr_reader :num_processed, :notifications, :delivered, :failed, :retryable
|
|
7
8
|
|
|
@@ -31,16 +32,21 @@ module Rpush
|
|
|
31
32
|
@retryable[deliver_after] ||= []
|
|
32
33
|
@retryable[deliver_after] << notification
|
|
33
34
|
end
|
|
35
|
+
|
|
34
36
|
Rpush::Daemon.store.mark_retryable(notification, deliver_after, persist: false)
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
def mark_all_retryable(deliver_after)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
end
|
|
39
|
+
def mark_all_retryable(deliver_after, error)
|
|
40
|
+
retryable_count = 0
|
|
41
|
+
|
|
41
42
|
each_notification do |notification|
|
|
42
|
-
|
|
43
|
+
next if notification.delivered || notification.failed
|
|
44
|
+
|
|
45
|
+
retryable_count += 1
|
|
46
|
+
mark_retryable(notification, deliver_after)
|
|
43
47
|
end
|
|
48
|
+
|
|
49
|
+
log_warn("Will retry #{retryable_count} of #{@notifications.size} notifications after #{deliver_after.strftime('%Y-%m-%d %H:%M:%S')} due to error (#{error.class.name}, #{error.message})")
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
def mark_delivered(notification)
|
|
@@ -54,6 +60,7 @@ module Rpush
|
|
|
54
60
|
@mutex.synchronize do
|
|
55
61
|
@delivered = @notifications
|
|
56
62
|
end
|
|
63
|
+
|
|
57
64
|
each_notification do |notification|
|
|
58
65
|
Rpush::Daemon.store.mark_delivered(notification, Time.now, persist: false)
|
|
59
66
|
end
|
|
@@ -20,8 +20,7 @@ module Rpush
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def mark_batch_retryable(deliver_after, error)
|
|
23
|
-
|
|
24
|
-
@batch.mark_all_retryable(deliver_after)
|
|
23
|
+
@batch.mark_all_retryable(deliver_after, error)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def mark_delivered
|
|
@@ -67,7 +67,7 @@ module Rpush
|
|
|
67
67
|
|
|
68
68
|
def check_database_is_connected
|
|
69
69
|
# Simply asking the adapter for the connection state is not sufficient.
|
|
70
|
-
Rpush::Client::ActiveRecord::Notification.
|
|
70
|
+
Rpush::Client::ActiveRecord::Notification.exists?
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def sleep_to_avoid_thrashing
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "webpush"
|
|
4
|
+
|
|
5
|
+
module Rpush
|
|
6
|
+
module Daemon
|
|
7
|
+
module Webpush
|
|
8
|
+
|
|
9
|
+
# Webpush::Request handles all the encryption / signing.
|
|
10
|
+
# We just override #perform to inject the http instance that is managed
|
|
11
|
+
# by Rpush.
|
|
12
|
+
#
|
|
13
|
+
class Request < ::Webpush::Request
|
|
14
|
+
def perform(http)
|
|
15
|
+
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
|
16
|
+
req.body = body
|
|
17
|
+
http.request(uri, req)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Delivery < Rpush::Daemon::Delivery
|
|
22
|
+
|
|
23
|
+
OK = [ 200, 201, 202 ].freeze
|
|
24
|
+
TEMPORARY_FAILURES = [ 429, 500, 502, 503, 504 ].freeze
|
|
25
|
+
|
|
26
|
+
def initialize(app, http, notification, batch)
|
|
27
|
+
@app = app
|
|
28
|
+
@http = http
|
|
29
|
+
@notification = notification
|
|
30
|
+
@batch = batch
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def perform
|
|
34
|
+
response = send_request
|
|
35
|
+
process_response response
|
|
36
|
+
rescue SocketError, SystemCallError => error
|
|
37
|
+
mark_retryable(@notification, Time.now + 10.seconds, error)
|
|
38
|
+
raise
|
|
39
|
+
rescue StandardError => error
|
|
40
|
+
mark_failed(error)
|
|
41
|
+
raise
|
|
42
|
+
ensure
|
|
43
|
+
@batch.notification_processed
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def send_request
|
|
49
|
+
# The initializer is inherited from Webpush::Request and looks like
|
|
50
|
+
# this:
|
|
51
|
+
#
|
|
52
|
+
# initialize(message: '', subscription:, vapid:, **options)
|
|
53
|
+
#
|
|
54
|
+
# where subscription is a hash of :endpoint and :keys, and vapid
|
|
55
|
+
# holds the vapid public and private keys and the :subject (which is
|
|
56
|
+
# an email address).
|
|
57
|
+
Request.new(
|
|
58
|
+
message: @notification.message,
|
|
59
|
+
subscription: @notification.subscription,
|
|
60
|
+
vapid: @app.vapid,
|
|
61
|
+
ttl: @notification.time_to_live,
|
|
62
|
+
urgency: @notification.urgency
|
|
63
|
+
).perform(@http)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def process_response(response)
|
|
67
|
+
case response.code.to_i
|
|
68
|
+
when *OK
|
|
69
|
+
mark_delivered
|
|
70
|
+
when *TEMPORARY_FAILURES
|
|
71
|
+
retry_delivery(response)
|
|
72
|
+
else
|
|
73
|
+
fail_delivery(response)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def retry_delivery(response)
|
|
78
|
+
time = deliver_after_header(response)
|
|
79
|
+
if time
|
|
80
|
+
mark_retryable(@notification, time)
|
|
81
|
+
else
|
|
82
|
+
mark_retryable_exponential(@notification)
|
|
83
|
+
end
|
|
84
|
+
log_info("Webpush endpoint responded with a #{response.code} error. #{retry_message}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def fail_delivery(response)
|
|
88
|
+
fail_message = fail_message(response)
|
|
89
|
+
log_error("#{@notification.id} failed: #{fail_message}")
|
|
90
|
+
fail Rpush::DeliveryError.new(response.code.to_i, @notification.id, fail_message)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def deliver_after_header(response)
|
|
94
|
+
Rpush::Daemon::RetryHeaderParser.parse(response.header['retry-after'])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def retry_message
|
|
98
|
+
deliver_after = @notification.deliver_after.strftime('%Y-%m-%d %H:%M:%S')
|
|
99
|
+
"Notification #{@notification.id} will be retried after #{deliver_after} (retry #{@notification.retries})."
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def fail_message(response)
|
|
103
|
+
msg = Rpush::Daemon::HTTP_STATUS_CODES[response.code.to_i]
|
|
104
|
+
if explanation = response.body.to_s[0..200].presence
|
|
105
|
+
msg += ": #{explanation}"
|
|
106
|
+
end
|
|
107
|
+
msg
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
data/lib/rpush/logger.rb
CHANGED
data/lib/rpush/version.rb
CHANGED
|
@@ -42,6 +42,7 @@ describe 'APNs http2 adapter' do
|
|
|
42
42
|
app.certificate = TEST_CERT
|
|
43
43
|
app.name = 'test'
|
|
44
44
|
app.environment = 'development'
|
|
45
|
+
app.bundle_id = 'com.example.app'
|
|
45
46
|
app.save!
|
|
46
47
|
app
|
|
47
48
|
end
|
|
@@ -75,7 +76,13 @@ describe 'APNs http2 adapter' do
|
|
|
75
76
|
:post,
|
|
76
77
|
"/3/device/#{fake_device_token}",
|
|
77
78
|
{ body: "{\"aps\":{\"alert\":\"test\",\"sound\":\"default\",\"content-available\":1}}",
|
|
78
|
-
headers: {
|
|
79
|
+
headers: {
|
|
80
|
+
'apns-expiration' => '0',
|
|
81
|
+
'apns-priority' => '10',
|
|
82
|
+
'apns-topic' => 'com.example.app',
|
|
83
|
+
'apns-push-type' => 'background'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
79
86
|
)
|
|
80
87
|
.and_return(fake_http2_request)
|
|
81
88
|
|
|
@@ -104,7 +111,12 @@ describe 'APNs http2 adapter' do
|
|
|
104
111
|
"/3/device/#{fake_device_token}",
|
|
105
112
|
{ body: "{\"aps\":{\"alert\":\"test\",\"sound\":\"default\","\
|
|
106
113
|
"\"content-available\":1},\"some_field\":\"some value\"}",
|
|
107
|
-
headers: {
|
|
114
|
+
headers: {
|
|
115
|
+
'apns-topic' => bundle_id,
|
|
116
|
+
'apns-expiration' => '0',
|
|
117
|
+
'apns-priority' => '10',
|
|
118
|
+
'apns-push-type' => 'background'
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
).and_return(fake_http2_request)
|
|
110
122
|
|
|
@@ -177,6 +189,13 @@ describe 'APNs http2 adapter' do
|
|
|
177
189
|
end
|
|
178
190
|
|
|
179
191
|
context 'when there is SocketError' do
|
|
192
|
+
let(:fake_http_resp_headers) {
|
|
193
|
+
{
|
|
194
|
+
":status" => "500",
|
|
195
|
+
"apns-id"=>"C6D65840-5E3F-785A-4D91-B97D305C12F6"
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
180
199
|
before(:each) do
|
|
181
200
|
expect(fake_client).to receive(:call_async) { raise(SocketError) }
|
|
182
201
|
end
|
|
@@ -201,6 +220,24 @@ describe 'APNs http2 adapter' do
|
|
|
201
220
|
notification = create_notification
|
|
202
221
|
Rpush.push
|
|
203
222
|
end
|
|
223
|
+
|
|
224
|
+
context 'when specific notification was delivered before request failed' do
|
|
225
|
+
let(:fake_http_resp_headers) {
|
|
226
|
+
{
|
|
227
|
+
":status" => "200",
|
|
228
|
+
"apns-id"=>"C6D65840-5E3F-785A-4D91-B97D305C12F6"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
it 'fails but will not retry this notification' do
|
|
233
|
+
notification = create_notification
|
|
234
|
+
expect do
|
|
235
|
+
Rpush.push
|
|
236
|
+
notification.reload
|
|
237
|
+
end.to change(notification, :retries).by(0)
|
|
238
|
+
.and change(notification, :delivered).to(true)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
204
241
|
end
|
|
205
242
|
|
|
206
243
|
context 'when any StandardError occurs' do
|
|
@@ -228,5 +265,65 @@ describe 'APNs http2 adapter' do
|
|
|
228
265
|
Rpush.push
|
|
229
266
|
end
|
|
230
267
|
end
|
|
268
|
+
|
|
269
|
+
context 'when waiting for requests to complete times out' do
|
|
270
|
+
let(:on_close) do
|
|
271
|
+
proc { |&block| @thread = Thread.new { sleep(0.01) } }
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
before(:each) do
|
|
275
|
+
@thread = nil
|
|
276
|
+
|
|
277
|
+
expect(fake_http2_request).
|
|
278
|
+
to receive(:on).with(:close), &on_close
|
|
279
|
+
|
|
280
|
+
expect(fake_client).to receive(:join) { @thread.join; raise(NetHttp2::AsyncRequestTimeout) }
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it 'closes the client' do
|
|
284
|
+
create_notification
|
|
285
|
+
expect(fake_client).to receive(:close)
|
|
286
|
+
Rpush.push
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it 'reflects :error' do
|
|
290
|
+
reflected_error = false
|
|
291
|
+
Rpush.reflect do |on|
|
|
292
|
+
on.error do |error|
|
|
293
|
+
reflected_error = true
|
|
294
|
+
expect(error).to be_kind_of(StandardError)
|
|
295
|
+
reflector.accept
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
notification = create_notification
|
|
300
|
+
Rpush.push
|
|
301
|
+
|
|
302
|
+
expect(reflected_error).to be true
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'fails but retries delivery several times' do
|
|
306
|
+
notification = create_notification
|
|
307
|
+
expect do
|
|
308
|
+
Rpush.push
|
|
309
|
+
notification.reload
|
|
310
|
+
end.to change(notification, :retries)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
context 'when specific notification was delivered before another async call failed' do
|
|
314
|
+
let(:on_close) do
|
|
315
|
+
proc { |&block| @thread = Thread.new { sleep(0.01); block.call } }
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it 'fails but retries delivery several times' do
|
|
319
|
+
notification = create_notification
|
|
320
|
+
expect do
|
|
321
|
+
Rpush.push
|
|
322
|
+
notification.reload
|
|
323
|
+
end.to change(notification, :retries).by(0)
|
|
324
|
+
.and change(notification, :delivered).to(true)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
231
328
|
end
|
|
232
329
|
end
|