rpush 1.0.0 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -13,15 +13,25 @@ module Rpush
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def mark_retryable_exponential(notification)
|
16
|
-
mark_retryable(notification, Time.now + 2
|
16
|
+
mark_retryable(notification, Time.now + 2**(notification.retries + 1))
|
17
17
|
end
|
18
18
|
|
19
19
|
def mark_delivered
|
20
20
|
@batch.mark_delivered(@notification)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
@batch.
|
23
|
+
def mark_batch_delivered
|
24
|
+
@batch.mark_all_delivered
|
25
|
+
end
|
26
|
+
|
27
|
+
def mark_failed(error)
|
28
|
+
code = error.respond_to?(:code) ? error.code : nil
|
29
|
+
@batch.mark_failed(@notification, code, error.to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
def mark_batch_failed(error)
|
33
|
+
code = error.respond_to?(:code) ? error.code : nil
|
34
|
+
@batch.mark_all_failed(code, error.to_s)
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Rpush
|
2
2
|
class DeliveryError < StandardError
|
3
|
-
attr_reader :code, :
|
3
|
+
attr_reader :code, :notification_id
|
4
4
|
|
5
5
|
def initialize(code, notification_id, description)
|
6
6
|
@code = code
|
@@ -13,7 +13,15 @@ module Rpush
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def message
|
16
|
-
|
16
|
+
error_str = [@code, "(#{@description})"].compact.join(' ')
|
17
|
+
"Unable to deliver notification #{@notification_id}, received error #{error_str}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
other.is_a?(DeliveryError) && \
|
22
|
+
other.code == code && \
|
23
|
+
other.notification_id == notification_id && \
|
24
|
+
other.to_s == to_s
|
17
25
|
end
|
18
26
|
end
|
19
27
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
module Dispatcher
|
4
|
+
class ApnsTcp < Rpush::Daemon::Dispatcher::Tcp
|
5
|
+
include Loggable
|
6
|
+
|
7
|
+
SELECT_TIMEOUT = 10
|
8
|
+
ERROR_TUPLE_BYTES = 6
|
9
|
+
APNS_ERRORS = {
|
10
|
+
1 => 'Processing error',
|
11
|
+
2 => 'Missing device token',
|
12
|
+
3 => 'Missing topic',
|
13
|
+
4 => 'Missing payload',
|
14
|
+
5 => 'Missing token size',
|
15
|
+
6 => 'Missing topic size',
|
16
|
+
7 => 'Missing payload size',
|
17
|
+
8 => 'Invalid token',
|
18
|
+
255 => 'None (unknown error)'
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super
|
23
|
+
@dispatch_mutex = Mutex.new
|
24
|
+
@stop_error_receiver = false
|
25
|
+
start_error_receiver
|
26
|
+
end
|
27
|
+
|
28
|
+
def dispatch(payload)
|
29
|
+
@dispatch_mutex.synchronize do
|
30
|
+
@delivery_class.new(@app, connection, payload.batch).perform
|
31
|
+
record_batch(payload.batch)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def cleanup
|
36
|
+
@stop_error_receiver = true
|
37
|
+
super
|
38
|
+
@error_receiver_thread.join if @error_receiver_thread
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def start_error_receiver
|
44
|
+
@error_receiver_thread = Thread.new do
|
45
|
+
check_for_error until @stop_error_receiver
|
46
|
+
Rpush::Daemon.store.release_connection
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def delivered_buffer
|
51
|
+
@delivered_buffer ||= RingBuffer.new(Rpush.config.batch_size * 10)
|
52
|
+
end
|
53
|
+
|
54
|
+
def record_batch(batch)
|
55
|
+
batch.each_delivered do |notification|
|
56
|
+
delivered_buffer << notification.id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_for_error
|
61
|
+
begin
|
62
|
+
return unless connection.select(SELECT_TIMEOUT)
|
63
|
+
rescue Errno::EBADF
|
64
|
+
# Connection closed, daemon is shutting down.
|
65
|
+
return
|
66
|
+
end
|
67
|
+
|
68
|
+
tuple = connection.read(ERROR_TUPLE_BYTES)
|
69
|
+
@dispatch_mutex.synchronize { handle_error_response(tuple) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def handle_error_response(tuple)
|
73
|
+
if tuple
|
74
|
+
_, code, notification_id = tuple.unpack('ccN')
|
75
|
+
handle_error(code, notification_id)
|
76
|
+
else
|
77
|
+
handle_disconnect
|
78
|
+
end
|
79
|
+
|
80
|
+
log_error('Error received, reconnecting...')
|
81
|
+
connection.reconnect
|
82
|
+
ensure
|
83
|
+
delivered_buffer.clear
|
84
|
+
end
|
85
|
+
|
86
|
+
def handle_disconnect
|
87
|
+
log_error('The APNs disconnected without returning an error. Marking all notifications delivered via this connection as failed.')
|
88
|
+
Rpush::Daemon.store.mark_ids_failed(delivered_buffer, nil, 'The APNs disconnected without returning an error. This may indicate you are using an invalid certificate.', Time.now)
|
89
|
+
end
|
90
|
+
|
91
|
+
def handle_error(code, notification_id)
|
92
|
+
failed_pos = delivered_buffer.index(notification_id)
|
93
|
+
description = APNS_ERRORS[code.to_i] || "Unknown error code #{code.inspect}. Possible Rpush bug?"
|
94
|
+
Rpush::Daemon.store.mark_ids_failed([notification_id], code, description, Time.now)
|
95
|
+
|
96
|
+
if failed_pos
|
97
|
+
retry_ids = delivered_buffer[(failed_pos + 1)..-1]
|
98
|
+
Rpush::Daemon.store.mark_ids_retryable(retry_ids, Time.now) if retry_ids.size > 0
|
99
|
+
elsif delivered_buffer.size > 0
|
100
|
+
log_error("Delivery sequence unknown for notifications following #{notification_id}.")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -2,14 +2,14 @@ module Rpush
|
|
2
2
|
module Daemon
|
3
3
|
module Dispatcher
|
4
4
|
class Http
|
5
|
-
def initialize(app, delivery_class,
|
5
|
+
def initialize(app, delivery_class, _options = {})
|
6
6
|
@app = app
|
7
7
|
@delivery_class = delivery_class
|
8
8
|
@http = Net::HTTP::Persistent.new('rpush')
|
9
9
|
end
|
10
10
|
|
11
|
-
def dispatch(
|
12
|
-
@delivery_class.new(@app, @http, notification, batch).perform
|
11
|
+
def dispatch(payload)
|
12
|
+
@delivery_class.new(@app, @http, payload.notification, payload.batch).perform
|
13
13
|
end
|
14
14
|
|
15
15
|
def cleanup
|
@@ -8,15 +8,15 @@ module Rpush
|
|
8
8
|
@host, @port = options[:host].call(@app)
|
9
9
|
end
|
10
10
|
|
11
|
-
def dispatch(
|
12
|
-
@delivery_class.new(@app, connection, notification, batch).perform
|
11
|
+
def dispatch(payload)
|
12
|
+
@delivery_class.new(@app, connection, payload.notification, payload.batch).perform
|
13
13
|
end
|
14
14
|
|
15
15
|
def cleanup
|
16
16
|
@connection.close if @connection
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
protected
|
20
20
|
|
21
21
|
def connection
|
22
22
|
return @connection if defined? @connection
|
@@ -2,15 +2,25 @@ module Rpush
|
|
2
2
|
module Daemon
|
3
3
|
class DispatcherLoop
|
4
4
|
include Reflectable
|
5
|
+
include Loggable
|
6
|
+
|
7
|
+
attr_reader :started_at, :dispatch_count
|
5
8
|
|
6
9
|
WAKEUP = :wakeup
|
7
10
|
|
8
11
|
def initialize(queue, dispatcher)
|
9
12
|
@queue = queue
|
10
13
|
@dispatcher = dispatcher
|
14
|
+
@dispatch_count = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def thread_status
|
18
|
+
@thread ? @thread.status : 'not started'
|
11
19
|
end
|
12
20
|
|
13
21
|
def start
|
22
|
+
@started_at = Time.now
|
23
|
+
|
14
24
|
@thread = Thread.new do
|
15
25
|
loop do
|
16
26
|
dispatch
|
@@ -37,16 +47,15 @@ module Rpush
|
|
37
47
|
protected
|
38
48
|
|
39
49
|
def dispatch
|
40
|
-
|
41
|
-
return if
|
50
|
+
payload = @queue.pop
|
51
|
+
return if payload == WAKEUP
|
42
52
|
|
43
53
|
begin
|
44
|
-
@
|
54
|
+
@dispatch_count += 1
|
55
|
+
@dispatcher.dispatch(payload)
|
45
56
|
rescue StandardError => e
|
46
|
-
|
57
|
+
log_error(e)
|
47
58
|
reflect(:error, e)
|
48
|
-
ensure
|
49
|
-
batch.notification_dispatched
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rpush
|
2
|
+
class CertificateExpiredError < StandardError
|
3
|
+
attr_reader :app, :time
|
4
|
+
|
5
|
+
def initialize(app, time)
|
6
|
+
@app = app
|
7
|
+
@time = time
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
message
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
"#{app.name} certificate expired at #{time}."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/rpush/daemon/feeder.rb
CHANGED
@@ -4,63 +4,52 @@ module Rpush
|
|
4
4
|
extend Reflectable
|
5
5
|
|
6
6
|
def self.start
|
7
|
-
|
8
|
-
|
9
|
-
if Rpush.config.embedded
|
10
|
-
Thread.new { feed_forever }
|
11
|
-
elsif Rpush.config.push
|
12
|
-
enqueue_notifications
|
13
|
-
else
|
14
|
-
feed_forever
|
15
|
-
end
|
7
|
+
self.should_stop = false
|
8
|
+
Rpush.config.push ? enqueue_notifications : feed_forever
|
16
9
|
end
|
17
10
|
|
18
11
|
def self.stop
|
19
|
-
|
20
|
-
|
12
|
+
self.should_stop = true
|
13
|
+
interruptible_sleeper.stop
|
14
|
+
@thread.join if @thread
|
21
15
|
end
|
22
16
|
|
23
|
-
def self.
|
24
|
-
interruptible_sleeper.
|
17
|
+
def self.wakeup
|
18
|
+
interruptible_sleeper.wakeup
|
25
19
|
end
|
26
20
|
|
27
|
-
|
21
|
+
class << self
|
22
|
+
attr_accessor :should_stop
|
23
|
+
end
|
28
24
|
|
29
25
|
def self.feed_forever
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
26
|
+
@thread = Thread.new do
|
27
|
+
loop do
|
28
|
+
enqueue_notifications
|
29
|
+
interruptible_sleeper.sleep
|
30
|
+
break if should_stop
|
31
|
+
end
|
32
|
+
|
33
|
+
Rpush::Daemon.store.release_connection
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
# :nocov:
|
40
|
-
def self.stop?
|
41
|
-
@stop
|
36
|
+
@thread.join
|
42
37
|
end
|
43
38
|
|
44
39
|
def self.enqueue_notifications
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
reflect(:error, e)
|
53
|
-
end
|
40
|
+
batch_size = Rpush.config.batch_size - Rpush::Daemon::AppRunner.num_queued
|
41
|
+
return if batch_size <= 0
|
42
|
+
notifications = Rpush::Daemon.store.deliverable_notifications(batch_size)
|
43
|
+
Rpush::Daemon::AppRunner.enqueue(notifications)
|
44
|
+
rescue StandardError => e
|
45
|
+
Rpush.logger.error(e)
|
46
|
+
reflect(:error, e)
|
54
47
|
end
|
55
48
|
|
56
49
|
def self.interruptible_sleeper
|
57
50
|
return @interruptible_sleeper if @interruptible_sleeper
|
58
|
-
|
59
|
-
@interruptible_sleeper
|
60
|
-
if Rpush.config.wakeup
|
61
|
-
@interruptible_sleeper.enable_wake_on_udp Rpush.config.wakeup[:bind], Rpush.config.wakeup[:port]
|
62
|
-
end
|
63
|
-
|
51
|
+
@interruptible_sleeper = InterruptibleSleep.new(Rpush.config.push_poll)
|
52
|
+
@interruptible_sleeper.start
|
64
53
|
@interruptible_sleeper
|
65
54
|
end
|
66
55
|
end
|
@@ -1,15 +1,14 @@
|
|
1
1
|
module Rpush
|
2
2
|
module Daemon
|
3
3
|
module Gcm
|
4
|
-
|
5
4
|
# http://developer.android.com/guide/google/gcm/gcm.html#response
|
6
5
|
class Delivery < Rpush::Daemon::Delivery
|
7
6
|
include MultiJsonHelper
|
8
7
|
|
9
8
|
host = ENV["RPUSH_GCM_HOST"] || "https://android.googleapis.com"
|
10
9
|
GCM_URI = URI.parse("#{host}/gcm/send")
|
11
|
-
UNAVAILABLE_STATES =
|
12
|
-
INVALID_REGISTRATION_ID_STATES =
|
10
|
+
UNAVAILABLE_STATES = %w(Unavailable InternalServerError)
|
11
|
+
INVALID_REGISTRATION_ID_STATES = %w(InvalidRegistration MismatchSenderId NotRegistered InvalidPackageName)
|
13
12
|
|
14
13
|
def initialize(app, http, notification, batch)
|
15
14
|
@app = app
|
@@ -19,12 +18,12 @@ module Rpush
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def perform
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
handle_response(do_post)
|
22
|
+
rescue StandardError => error
|
23
|
+
mark_failed(error)
|
24
|
+
raise
|
25
|
+
ensure
|
26
|
+
@batch.notification_processed
|
28
27
|
end
|
29
28
|
|
30
29
|
protected
|
@@ -42,7 +41,7 @@ module Rpush
|
|
42
41
|
when 503
|
43
42
|
service_unavailable(response)
|
44
43
|
else
|
45
|
-
|
44
|
+
fail Rpush::DeliveryError.new(response.code, @notification.id, Rpush::Daemon::HTTP_STATUS_CODES[response.code.to_i])
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
@@ -69,9 +68,8 @@ module Rpush
|
|
69
68
|
def handle_successes(successes)
|
70
69
|
successes.each do |result|
|
71
70
|
reflect(:gcm_delivered_to_recipient, @notification, result[:registration_id])
|
72
|
-
|
73
|
-
|
74
|
-
end
|
71
|
+
next unless result.key?(:canonical_id)
|
72
|
+
reflect(:gcm_canonical_id, result[:registration_id], result[:canonical_id])
|
75
73
|
end
|
76
74
|
end
|
77
75
|
|
@@ -86,7 +84,7 @@ module Rpush
|
|
86
84
|
failures.description += " #{unavailable_idxs.join(', ')} will be retried as notification #{new_notification.id}."
|
87
85
|
end
|
88
86
|
handle_errors(failures)
|
89
|
-
|
87
|
+
fail Rpush::DeliveryError.new(nil, @notification.id, failures.description)
|
90
88
|
end
|
91
89
|
end
|
92
90
|
|
@@ -103,15 +101,15 @@ module Rpush
|
|
103
101
|
attrs = @notification.attributes.slice('app_id', 'collapse_key', 'delay_while_idle')
|
104
102
|
registration_ids = @notification.registration_ids.values_at(*unavailable_idxs)
|
105
103
|
Rpush::Daemon.store.create_gcm_notification(attrs, @notification.data,
|
106
|
-
|
104
|
+
registration_ids, deliver_after_header(response), @notification.app)
|
107
105
|
end
|
108
106
|
|
109
107
|
def bad_request
|
110
|
-
|
108
|
+
fail Rpush::DeliveryError.new(400, @notification.id, 'GCM failed to parse the JSON request. Possibly an Rpush bug, please open an issue.')
|
111
109
|
end
|
112
110
|
|
113
111
|
def unauthorized
|
114
|
-
|
112
|
+
fail Rpush::DeliveryError.new(401, @notification.id, 'Unauthorized, check your App auth_key.')
|
115
113
|
end
|
116
114
|
|
117
115
|
def internal_server_error(response)
|
@@ -129,7 +127,8 @@ module Rpush
|
|
129
127
|
end
|
130
128
|
|
131
129
|
def retry_delivery(notification, response)
|
132
|
-
|
130
|
+
time = deliver_after_header(response)
|
131
|
+
if time
|
133
132
|
mark_retryable(notification, time)
|
134
133
|
else
|
135
134
|
mark_retryable_exponential(notification)
|
@@ -141,8 +140,8 @@ module Rpush
|
|
141
140
|
end
|
142
141
|
|
143
142
|
def do_post
|
144
|
-
post = Net::HTTP::Post.new(GCM_URI.path,
|
145
|
-
|
143
|
+
post = Net::HTTP::Post.new(GCM_URI.path, 'Content-Type' => 'application/json',
|
144
|
+
'Authorization' => "key=#{@notification.app.auth_key}")
|
146
145
|
post.body = @notification.as_json.to_json
|
147
146
|
@http.request(GCM_URI, post)
|
148
147
|
end
|