rpush 1.0.0 → 2.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +12 -14
- data/bin/rpush +11 -2
- data/lib/generators/rpush_generator.rb +2 -0
- data/lib/generators/templates/add_adm.rb +5 -5
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
- data/lib/generators/templates/add_app_to_rapns.rb +2 -2
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
- data/lib/generators/templates/add_gcm.rb +32 -32
- data/lib/generators/templates/add_rpush.rb +67 -67
- data/lib/generators/templates/add_wpns.rb +2 -2
- data/lib/generators/templates/create_rapns_apps.rb +5 -5
- data/lib/generators/templates/create_rapns_feedback.rb +2 -2
- data/lib/generators/templates/create_rapns_notifications.rb +15 -15
- data/lib/generators/templates/rpush.rb +10 -7
- data/lib/generators/templates/rpush_2_0_0_updates.rb +23 -0
- data/lib/rpush.rb +4 -28
- data/lib/rpush/client/active_model.rb +21 -0
- data/lib/rpush/client/active_model/adm/app.rb +23 -0
- data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
- data/lib/rpush/client/active_model/adm/notification.rb +28 -0
- data/lib/rpush/client/active_model/apns/app.rb +37 -0
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
- data/lib/rpush/client/active_model/apns/notification.rb +90 -0
- data/lib/rpush/client/active_model/gcm/app.rb +19 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
- data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
- data/lib/rpush/client/active_model/notification.rb +26 -0
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
- data/lib/rpush/client/active_model/wpns/app.rb +13 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
- data/lib/rpush/client/active_record.rb +19 -0
- data/lib/rpush/client/active_record/adm/app.rb +11 -0
- data/lib/rpush/client/active_record/adm/notification.rb +11 -0
- data/lib/rpush/client/active_record/apns/app.rb +11 -0
- data/lib/rpush/client/active_record/apns/feedback.rb +20 -0
- data/lib/rpush/client/active_record/apns/notification.rb +46 -0
- data/lib/rpush/client/active_record/app.rb +17 -0
- data/lib/rpush/client/active_record/gcm/app.rb +11 -0
- data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
- data/lib/rpush/client/active_record/notification.rb +38 -0
- data/lib/rpush/client/active_record/wpns/app.rb +11 -0
- data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +35 -0
- data/lib/rpush/client/redis/adm/app.rb +14 -0
- data/lib/rpush/client/redis/adm/notification.rb +11 -0
- data/lib/rpush/client/redis/apns/app.rb +11 -0
- data/lib/rpush/client/redis/apns/feedback.rb +20 -0
- data/lib/rpush/client/redis/apns/notification.rb +11 -0
- data/lib/rpush/client/redis/app.rb +22 -0
- data/lib/rpush/client/redis/gcm/app.rb +11 -0
- data/lib/rpush/client/redis/gcm/notification.rb +11 -0
- data/lib/rpush/client/redis/notification.rb +68 -0
- data/lib/rpush/client/redis/wpns/app.rb +11 -0
- data/lib/rpush/client/redis/wpns/notification.rb +11 -0
- data/lib/rpush/configuration.rb +27 -6
- data/lib/rpush/daemon.rb +36 -56
- data/lib/rpush/daemon/adm/delivery.rb +50 -52
- data/lib/rpush/daemon/apns.rb +6 -5
- data/lib/rpush/daemon/apns/delivery.rb +20 -44
- data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
- data/lib/rpush/daemon/app_runner.rb +67 -60
- data/lib/rpush/daemon/batch.rb +54 -40
- data/lib/rpush/daemon/delivery.rb +13 -3
- data/lib/rpush/daemon/delivery_error.rb +10 -2
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +106 -0
- data/lib/rpush/daemon/dispatcher/http.rb +3 -3
- data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
- data/lib/rpush/daemon/dispatcher_loop.rb +15 -6
- data/lib/rpush/daemon/errors.rb +18 -0
- data/lib/rpush/daemon/feeder.rb +28 -39
- data/lib/rpush/daemon/gcm/delivery.rb +19 -20
- data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
- data/lib/rpush/daemon/loggable.rb +2 -4
- data/lib/rpush/daemon/proc_title.rb +16 -0
- data/lib/rpush/daemon/queue_payload.rb +12 -0
- data/lib/rpush/daemon/reflectable.rb +3 -5
- data/lib/rpush/daemon/retry_header_parser.rb +6 -6
- data/lib/rpush/daemon/ring_buffer.rb +16 -0
- data/lib/rpush/daemon/service_config_methods.rb +23 -7
- data/lib/rpush/daemon/signal_handler.rb +51 -0
- data/lib/rpush/daemon/store/active_record.rb +71 -38
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +15 -15
- data/lib/rpush/daemon/store/interface.rb +19 -0
- data/lib/rpush/daemon/store/redis.rb +149 -0
- data/lib/rpush/daemon/tcp_connection.rb +6 -11
- data/lib/rpush/daemon/wpns/delivery.rb +21 -30
- data/lib/rpush/deprecatable.rb +4 -3
- data/lib/rpush/deprecation.rb +7 -10
- data/lib/rpush/embed.rb +7 -2
- data/lib/rpush/logger.rb +11 -15
- data/lib/rpush/push.rb +0 -1
- data/lib/rpush/reflection.rb +6 -12
- data/lib/rpush/version.rb +1 -1
- data/lib/tasks/quality.rake +34 -0
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +3 -6
- data/spec/functional/apns_spec.rb +118 -24
- data/spec/functional/embed_spec.rb +22 -20
- data/spec/functional/gcm_spec.rb +4 -7
- data/spec/functional/new_app_spec.rb +61 -0
- data/spec/functional/retry_spec.rb +46 -0
- data/spec/functional/wpns_spec.rb +3 -6
- data/spec/functional_spec_helper.rb +26 -0
- data/spec/integration/rpush_spec.rb +13 -0
- data/spec/integration/support/gcm_success_response.json +1 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/active_record_setup.rb +48 -0
- data/{config → spec/support/config}/database.yml +0 -0
- data/spec/support/install.sh +43 -7
- data/spec/support/simplecov_helper.rb +9 -5
- data/spec/support/simplecov_quality_formatter.rb +10 -6
- data/spec/unit/apns_feedback_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
- data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
- data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
- data/spec/unit/client/active_record/app_spec.rb +30 -0
- data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
- data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/notification_spec.rb +15 -0
- data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
- data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
- data/spec/unit/configuration_spec.rb +12 -5
- data/spec/unit/daemon/adm/delivery_spec.rb +57 -54
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
- data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +24 -17
- data/spec/unit/daemon/app_runner_spec.rb +66 -123
- data/spec/unit/daemon/batch_spec.rb +52 -115
- data/spec/unit/daemon/delivery_spec.rb +15 -1
- data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
- data/spec/unit/daemon/dispatcher_loop_spec.rb +7 -12
- data/spec/unit/daemon/feeder_spec.rb +40 -39
- data/spec/unit/daemon/gcm/delivery_spec.rb +108 -89
- data/spec/unit/daemon/reflectable_spec.rb +2 -2
- data/spec/unit/daemon/retryable_error_spec.rb +1 -1
- data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
- data/spec/unit/daemon/signal_handler_spec.rb +72 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +9 -9
- data/spec/unit/daemon/store/active_record_spec.rb +38 -47
- data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
- data/spec/unit/daemon/too_many_requests_error_spec.rb +1 -1
- data/spec/unit/daemon/wpns/delivery_spec.rb +61 -50
- data/spec/unit/daemon_spec.rb +46 -81
- data/spec/unit/embed_spec.rb +4 -2
- data/spec/unit/logger_spec.rb +30 -40
- data/spec/unit/notification_shared.rb +9 -79
- data/spec/unit/push_spec.rb +3 -8
- data/spec/unit/reflection_spec.rb +25 -25
- data/spec/unit/rpush_spec.rb +1 -2
- data/spec/unit_spec_helper.rb +33 -88
- metadata +119 -67
- data/lib/rpush/TODO +0 -3
- data/lib/rpush/adm/app.rb +0 -15
- data/lib/rpush/adm/data_validator.rb +0 -11
- data/lib/rpush/adm/notification.rb +0 -29
- data/lib/rpush/apns/app.rb +0 -29
- data/lib/rpush/apns/binary_notification_validator.rb +0 -12
- data/lib/rpush/apns/device_token_format_validator.rb +0 -12
- data/lib/rpush/apns/feedback.rb +0 -16
- data/lib/rpush/apns/notification.rb +0 -84
- data/lib/rpush/app.rb +0 -18
- data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
- data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
- data/lib/rpush/gcm/app.rb +0 -11
- data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
- data/lib/rpush/gcm/notification.rb +0 -30
- data/lib/rpush/notification.rb +0 -69
- data/lib/rpush/notifier.rb +0 -52
- data/lib/rpush/payload_data_size_validator.rb +0 -10
- data/lib/rpush/railtie.rb +0 -11
- data/lib/rpush/registration_ids_count_validator.rb +0 -10
- data/lib/rpush/wpns/app.rb +0 -9
- data/lib/rpush/wpns/notification.rb +0 -26
- data/lib/tasks/cane.rake +0 -18
- data/lib/tasks/rpush.rake +0 -16
- data/spec/unit/apns/app_spec.rb +0 -29
- data/spec/unit/apns/feedback_spec.rb +0 -9
- data/spec/unit/apns/notification_spec.rb +0 -208
- data/spec/unit/app_spec.rb +0 -30
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
- data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
- data/spec/unit/gcm/app_spec.rb +0 -4
- data/spec/unit/notification_spec.rb +0 -15
- data/spec/unit/notifier_spec.rb +0 -49
- data/spec/unit/wpns/app_spec.rb +0 -4
- data/spec/unit/wpns/notification_spec.rb +0 -30
data/lib/rpush/daemon/apns.rb
CHANGED
|
@@ -4,13 +4,14 @@ module Rpush
|
|
|
4
4
|
extend ServiceConfigMethods
|
|
5
5
|
|
|
6
6
|
HOSTS = {
|
|
7
|
-
:
|
|
8
|
-
:
|
|
9
|
-
:
|
|
7
|
+
production: ['gateway.push.apple.com', 2195],
|
|
8
|
+
development: ['gateway.sandbox.push.apple.com', 2195], # deprecated
|
|
9
|
+
sandbox: ['gateway.sandbox.push.apple.com', 2195]
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
batch_deliveries true
|
|
13
|
+
dispatcher :apns_tcp, host: proc { |app| HOSTS[app.environment.to_sym] }
|
|
14
|
+
loops Rpush::Daemon::Apns::FeedbackReceiver, if: -> { !Rpush.config.push }
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -2,60 +2,36 @@ module Rpush
|
|
|
2
2
|
module Daemon
|
|
3
3
|
module Apns
|
|
4
4
|
class Delivery < Rpush::Daemon::Delivery
|
|
5
|
-
|
|
6
|
-
ERROR_TUPLE_BYTES = 6
|
|
7
|
-
APN_ERRORS = {
|
|
8
|
-
1 => "Processing error",
|
|
9
|
-
2 => "Missing device token",
|
|
10
|
-
3 => "Missing topic",
|
|
11
|
-
4 => "Missing payload",
|
|
12
|
-
5 => "Missing token size",
|
|
13
|
-
6 => "Missing topic size",
|
|
14
|
-
7 => "Missing payload size",
|
|
15
|
-
8 => "Invalid token",
|
|
16
|
-
255 => "None (unknown error)"
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
def initialize(app, conneciton, notification, batch)
|
|
5
|
+
def initialize(app, connection, batch)
|
|
20
6
|
@app = app
|
|
21
|
-
@connection =
|
|
22
|
-
@notification = notification
|
|
7
|
+
@connection = connection
|
|
23
8
|
@batch = batch
|
|
24
9
|
end
|
|
25
10
|
|
|
26
11
|
def perform
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
12
|
+
@connection.write(batch_to_binary)
|
|
13
|
+
mark_batch_delivered
|
|
14
|
+
describe_deliveries
|
|
15
|
+
rescue StandardError => error
|
|
16
|
+
mark_batch_failed(error)
|
|
17
|
+
raise
|
|
18
|
+
ensure
|
|
19
|
+
@batch.all_processed
|
|
36
20
|
end
|
|
37
21
|
|
|
38
22
|
protected
|
|
39
23
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
description = APN_ERRORS[code.to_i] || "Unknown error. Possible Rpush bug?"
|
|
48
|
-
error = Rpush::DeliveryError.new(code, notification_id, description)
|
|
49
|
-
else
|
|
50
|
-
error = Rpush::Apns::DisconnectionError.new
|
|
51
|
-
end
|
|
24
|
+
def batch_to_binary
|
|
25
|
+
payload = ""
|
|
26
|
+
@batch.each_notification do |notification|
|
|
27
|
+
payload << notification.to_binary
|
|
28
|
+
end
|
|
29
|
+
payload
|
|
30
|
+
end
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
ensure
|
|
57
|
-
raise error if error
|
|
58
|
-
end
|
|
32
|
+
def describe_deliveries
|
|
33
|
+
@batch.each_notification do |notification|
|
|
34
|
+
log_info("#{notification.id} sent to #{notification.device_token}")
|
|
59
35
|
end
|
|
60
36
|
end
|
|
61
37
|
end
|
|
@@ -7,28 +7,29 @@ module Rpush
|
|
|
7
7
|
|
|
8
8
|
TUPLE_BYTES = 38
|
|
9
9
|
HOSTS = {
|
|
10
|
-
:
|
|
11
|
-
:
|
|
12
|
-
:
|
|
10
|
+
production: ['feedback.push.apple.com', 2196],
|
|
11
|
+
development: ['feedback.sandbox.push.apple.com', 2196], # deprecated
|
|
12
|
+
sandbox: ['feedback.sandbox.push.apple.com', 2196]
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
def initialize(app)
|
|
16
16
|
@app = app
|
|
17
17
|
@host, @port = HOSTS[@app.environment.to_sym]
|
|
18
|
-
@poll = Rpush.config.feedback_poll
|
|
19
18
|
@certificate = app.certificate
|
|
20
19
|
@password = app.password
|
|
21
|
-
@interruptible_sleep = InterruptibleSleep.new
|
|
20
|
+
@interruptible_sleep = InterruptibleSleep.new(Rpush.config.feedback_poll)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def start
|
|
25
24
|
return if Rpush.config.push
|
|
25
|
+
log_info("APNs Feedback Receiver started.")
|
|
26
|
+
@interruptible_sleep.start
|
|
26
27
|
|
|
27
28
|
@thread = Thread.new do
|
|
28
29
|
loop do
|
|
29
30
|
break if @stop
|
|
30
31
|
check_for_feedback
|
|
31
|
-
@interruptible_sleep.sleep
|
|
32
|
+
@interruptible_sleep.sleep
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
Rpush::Daemon.store.release_connection
|
|
@@ -37,7 +38,7 @@ module Rpush
|
|
|
37
38
|
|
|
38
39
|
def stop
|
|
39
40
|
@stop = true
|
|
40
|
-
@interruptible_sleep.
|
|
41
|
+
@interruptible_sleep.stop
|
|
41
42
|
@thread.join if @thread
|
|
42
43
|
end
|
|
43
44
|
|
|
@@ -46,10 +47,12 @@ module Rpush
|
|
|
46
47
|
begin
|
|
47
48
|
connection = Rpush::Daemon::TcpConnection.new(@app, @host, @port)
|
|
48
49
|
connection.connect
|
|
50
|
+
tuple = connection.read(TUPLE_BYTES)
|
|
49
51
|
|
|
50
|
-
while tuple
|
|
52
|
+
while tuple
|
|
51
53
|
timestamp, device_token = parse_tuple(tuple)
|
|
52
54
|
create_feedback(timestamp, device_token)
|
|
55
|
+
tuple = connection.read(TUPLE_BYTES)
|
|
53
56
|
end
|
|
54
57
|
rescue StandardError => e
|
|
55
58
|
log_error(e)
|
|
@@ -13,20 +13,18 @@ module Rpush
|
|
|
13
13
|
|
|
14
14
|
def self.enqueue(notifications)
|
|
15
15
|
notifications.group_by(&:app_id).each do |app_id, group|
|
|
16
|
-
|
|
17
|
-
if
|
|
18
|
-
app.enqueue(batch)
|
|
19
|
-
else
|
|
20
|
-
Rpush.logger.error("No such app '#{app_id}' for notifications #{batch.describe}.")
|
|
21
|
-
end
|
|
16
|
+
sync_app_with_id(app_id) unless runners[app_id]
|
|
17
|
+
runners[app_id].enqueue(group) if runners[app_id]
|
|
22
18
|
end
|
|
19
|
+
ProcTitle.update
|
|
23
20
|
end
|
|
24
21
|
|
|
25
22
|
def self.sync
|
|
26
|
-
apps = Rpush::
|
|
23
|
+
apps = Rpush::Daemon.store.all_apps
|
|
27
24
|
apps.each { |app| sync_app(app) }
|
|
28
25
|
removed = runners.keys - apps.map(&:id)
|
|
29
26
|
removed.each { |app_id| runners.delete(app_id).stop }
|
|
27
|
+
ProcTitle.update
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
def self.sync_app(app)
|
|
@@ -35,8 +33,8 @@ module Rpush
|
|
|
35
33
|
else
|
|
36
34
|
runner = new(app)
|
|
37
35
|
begin
|
|
38
|
-
runner.start
|
|
39
36
|
runners[app.id] = runner
|
|
37
|
+
runner.start
|
|
40
38
|
rescue StandardError => e
|
|
41
39
|
Rpush.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
|
42
40
|
Rpush.logger.error(e)
|
|
@@ -45,25 +43,28 @@ module Rpush
|
|
|
45
43
|
end
|
|
46
44
|
end
|
|
47
45
|
|
|
46
|
+
def self.sync_app_with_id(app_id)
|
|
47
|
+
sync_app(Rpush::Daemon.store.app(app_id))
|
|
48
|
+
end
|
|
49
|
+
|
|
48
50
|
def self.stop
|
|
49
51
|
runners.values.map(&:stop)
|
|
50
52
|
runners.clear
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
def self.
|
|
54
|
-
runners.values.
|
|
55
|
+
def self.num_dispatchers
|
|
56
|
+
runners.values.sum(&:num_dispatcher_loops)
|
|
55
57
|
end
|
|
56
58
|
|
|
57
|
-
def self.
|
|
58
|
-
runners.values.
|
|
59
|
+
def self.num_queued
|
|
60
|
+
runners.values.sum(&:queue_size)
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
def self.
|
|
62
|
-
|
|
63
|
+
def self.debug
|
|
64
|
+
runners.values.map(&:debug)
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
attr_reader :app
|
|
66
|
-
attr_accessor :batch
|
|
67
68
|
|
|
68
69
|
def initialize(app)
|
|
69
70
|
@app = app
|
|
@@ -71,27 +72,40 @@ module Rpush
|
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
def start
|
|
74
|
-
app.connections.times {
|
|
75
|
+
app.connections.times { dispatcher_loops.push(new_dispatcher_loop) }
|
|
75
76
|
start_loops
|
|
76
77
|
log_info("Started, #{dispatchers_str}.")
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
def stop
|
|
80
|
-
|
|
81
|
+
wait_until_idle
|
|
82
|
+
stop_dispatcher_loops
|
|
81
83
|
stop_loops
|
|
82
84
|
end
|
|
83
85
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
def wait_until_idle
|
|
87
|
+
sleep 0.5 while queue.size > 0
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def enqueue(notifications)
|
|
91
|
+
if service.batch_deliveries?
|
|
92
|
+
batch_size = (notifications.size / num_dispatcher_loops).ceil
|
|
93
|
+
notifications.in_groups_of(batch_size, false).each do |batch_notifications|
|
|
94
|
+
batch = Batch.new(batch_notifications)
|
|
95
|
+
queue.push(QueuePayload.new(batch))
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
batch = Batch.new(notifications)
|
|
99
|
+
notifications.each do |notification|
|
|
100
|
+
queue.push(QueuePayload.new(batch, notification))
|
|
101
|
+
reflect(:notification_enqueued, notification)
|
|
102
|
+
end
|
|
89
103
|
end
|
|
90
104
|
end
|
|
91
105
|
|
|
92
106
|
def sync(app)
|
|
93
107
|
@app = app
|
|
94
|
-
diff =
|
|
108
|
+
diff = dispatcher_loops.size - app.connections
|
|
95
109
|
return if diff == 0
|
|
96
110
|
if diff > 0
|
|
97
111
|
decrement_dispatchers(diff)
|
|
@@ -103,53 +117,41 @@ module Rpush
|
|
|
103
117
|
end
|
|
104
118
|
|
|
105
119
|
def decrement_dispatchers(num)
|
|
106
|
-
num.times {
|
|
120
|
+
num.times { dispatcher_loops.pop }
|
|
107
121
|
end
|
|
108
122
|
|
|
109
123
|
def increment_dispatchers(num)
|
|
110
|
-
num.times {
|
|
124
|
+
num.times { dispatcher_loops.push(new_dispatcher_loop) }
|
|
111
125
|
end
|
|
112
126
|
|
|
113
127
|
def debug
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
end
|
|
128
|
+
dispatcher_details = {}
|
|
129
|
+
|
|
130
|
+
dispatcher_loops.loops.each_with_index do |dispatcher_loop, i|
|
|
131
|
+
dispatcher_details[i] = {
|
|
132
|
+
started_at: dispatcher_loop.started_at.iso8601,
|
|
133
|
+
dispatched: dispatcher_loop.dispatch_count,
|
|
134
|
+
thread_status: dispatcher_loop.thread_status
|
|
135
|
+
}
|
|
136
|
+
end
|
|
124
137
|
|
|
125
|
-
|
|
126
|
-
|
|
138
|
+
runner_details = { dispatchers: dispatcher_details, queued: queue_size }
|
|
139
|
+
log_info(JSON.pretty_generate(runner_details))
|
|
127
140
|
end
|
|
128
141
|
|
|
129
142
|
def queue_size
|
|
130
143
|
queue.size
|
|
131
144
|
end
|
|
132
145
|
|
|
133
|
-
def
|
|
134
|
-
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def batch_processed
|
|
138
|
-
batch ? batch.num_processed : 0
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def num_dispatchers
|
|
142
|
-
dispatchers.size
|
|
146
|
+
def num_dispatcher_loops
|
|
147
|
+
dispatcher_loops.size
|
|
143
148
|
end
|
|
144
149
|
|
|
145
|
-
|
|
150
|
+
private
|
|
146
151
|
|
|
147
152
|
def start_loops
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
instance.start
|
|
151
|
-
@loops << instance
|
|
152
|
-
end
|
|
153
|
+
@loops = service.loop_instances(@app)
|
|
154
|
+
@loops.map(&:start)
|
|
153
155
|
end
|
|
154
156
|
|
|
155
157
|
def stop_loops
|
|
@@ -157,27 +159,32 @@ module Rpush
|
|
|
157
159
|
@loops = []
|
|
158
160
|
end
|
|
159
161
|
|
|
162
|
+
def stop_dispatcher_loops
|
|
163
|
+
dispatcher_loops.stop
|
|
164
|
+
@dispatcher_loops = nil
|
|
165
|
+
end
|
|
166
|
+
|
|
160
167
|
def new_dispatcher_loop
|
|
161
|
-
dispatcher =
|
|
168
|
+
dispatcher = service.new_dispatcher(@app)
|
|
162
169
|
dispatcher_loop = Rpush::Daemon::DispatcherLoop.new(queue, dispatcher)
|
|
163
170
|
dispatcher_loop.start
|
|
164
171
|
dispatcher_loop
|
|
165
172
|
end
|
|
166
173
|
|
|
167
|
-
def
|
|
168
|
-
return @
|
|
169
|
-
@
|
|
174
|
+
def service
|
|
175
|
+
return @service if defined? @service
|
|
176
|
+
@service = "Rpush::Daemon::#{@app.service_name.camelize}".constantize
|
|
170
177
|
end
|
|
171
178
|
|
|
172
179
|
def queue
|
|
173
180
|
@queue ||= Queue.new
|
|
174
181
|
end
|
|
175
182
|
|
|
176
|
-
def
|
|
177
|
-
@
|
|
183
|
+
def dispatcher_loops
|
|
184
|
+
@dispatcher_loops ||= Rpush::Daemon::DispatcherLoopCollection.new
|
|
178
185
|
end
|
|
179
186
|
|
|
180
|
-
def dispatchers_str(count =
|
|
187
|
+
def dispatchers_str(count = num_dispatcher_loops)
|
|
181
188
|
count = count.abs
|
|
182
189
|
str = count == 1 ? 'dispatcher' : 'dispatchers'
|
|
183
190
|
"#{count} #{str}"
|
data/lib/rpush/daemon/batch.rb
CHANGED
|
@@ -3,8 +3,7 @@ module Rpush
|
|
|
3
3
|
class Batch
|
|
4
4
|
include Reflectable
|
|
5
5
|
|
|
6
|
-
attr_reader :num_processed, :notifications,
|
|
7
|
-
:delivered, :failed, :retryable
|
|
6
|
+
attr_reader :num_processed, :notifications, :delivered, :failed, :retryable
|
|
8
7
|
|
|
9
8
|
def initialize(notifications)
|
|
10
9
|
@notifications = notifications
|
|
@@ -15,61 +14,80 @@ module Rpush
|
|
|
15
14
|
@mutex = Mutex.new
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
def
|
|
19
|
-
@
|
|
17
|
+
def complete?
|
|
18
|
+
@complete == true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def each_notification(&blk)
|
|
22
|
+
@notifications.each(&blk)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def each_delivered(&blk)
|
|
26
|
+
@delivered.each(&blk)
|
|
20
27
|
end
|
|
21
28
|
|
|
22
29
|
def mark_retryable(notification, deliver_after)
|
|
23
|
-
|
|
24
|
-
retryable[deliver_after] ||= []
|
|
25
|
-
retryable[deliver_after] << notification
|
|
26
|
-
Rpush::Daemon.store.mark_retryable(notification, deliver_after, :persist => false)
|
|
27
|
-
else
|
|
28
|
-
Rpush::Daemon.store.mark_retryable(notification, deliver_after)
|
|
29
|
-
reflect(:notification_will_retry, notification)
|
|
30
|
+
@mutex.synchronize do
|
|
31
|
+
@retryable[deliver_after] ||= []
|
|
32
|
+
@retryable[deliver_after] << notification
|
|
30
33
|
end
|
|
34
|
+
Rpush::Daemon.store.mark_retryable(notification, deliver_after, persist: false)
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
def mark_delivered(notification)
|
|
34
|
-
|
|
35
|
-
delivered << notification
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
@mutex.synchronize do
|
|
39
|
+
@delivered << notification
|
|
40
|
+
end
|
|
41
|
+
Rpush::Daemon.store.mark_delivered(notification, Time.now, persist: false)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def mark_all_delivered
|
|
45
|
+
@mutex.synchronize do
|
|
46
|
+
@delivered = @notifications
|
|
47
|
+
end
|
|
48
|
+
each_notification do |notification|
|
|
49
|
+
Rpush::Daemon.store.mark_delivered(notification, Time.now, persist: false)
|
|
40
50
|
end
|
|
41
51
|
end
|
|
42
52
|
|
|
43
53
|
def mark_failed(notification, code, description)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
failed[key] ||= []
|
|
47
|
-
failed[key] << notification
|
|
48
|
-
Rpush::Daemon.store.mark_failed(notification, code, description, Time.now, :persist => false)
|
|
49
|
-
else
|
|
50
|
-
Rpush::Daemon.store.mark_failed(notification, code, description, Time.now)
|
|
51
|
-
reflect(:notification_failed, notification)
|
|
54
|
+
key = [code, description]
|
|
55
|
+
@mutex.synchronize do
|
|
56
|
+
@failed[key] ||= []
|
|
57
|
+
@failed[key] << notification
|
|
52
58
|
end
|
|
59
|
+
Rpush::Daemon.store.mark_failed(notification, code, description, Time.now, persist: false)
|
|
53
60
|
end
|
|
54
61
|
|
|
55
|
-
def
|
|
62
|
+
def mark_all_failed(code, message)
|
|
63
|
+
key = [code, message]
|
|
56
64
|
@mutex.synchronize do
|
|
57
|
-
@
|
|
58
|
-
|
|
65
|
+
@failed[key] = @notifications
|
|
66
|
+
end
|
|
67
|
+
each_notification do |notification|
|
|
68
|
+
Rpush::Daemon.store.mark_failed(notification, code, message, Time.now, persist: false)
|
|
59
69
|
end
|
|
60
70
|
end
|
|
61
71
|
|
|
62
|
-
def
|
|
63
|
-
@
|
|
72
|
+
def notification_processed
|
|
73
|
+
@mutex.synchronize do
|
|
74
|
+
@num_processed += 1
|
|
75
|
+
complete if @num_processed >= @notifications.size
|
|
76
|
+
end
|
|
64
77
|
end
|
|
65
78
|
|
|
66
|
-
def
|
|
67
|
-
|
|
79
|
+
def all_processed
|
|
80
|
+
@mutex.synchronize do
|
|
81
|
+
@num_processed = @notifications.size
|
|
82
|
+
complete
|
|
83
|
+
end
|
|
68
84
|
end
|
|
69
85
|
|
|
70
86
|
private
|
|
71
87
|
|
|
72
88
|
def complete
|
|
89
|
+
return if complete?
|
|
90
|
+
|
|
73
91
|
[:complete_delivered, :complete_failed, :complete_retried].each do |method|
|
|
74
92
|
begin
|
|
75
93
|
send(method)
|
|
@@ -79,36 +97,32 @@ module Rpush
|
|
|
79
97
|
end
|
|
80
98
|
end
|
|
81
99
|
|
|
82
|
-
notifications.clear
|
|
83
100
|
@complete = true
|
|
84
101
|
end
|
|
85
102
|
|
|
86
103
|
def complete_delivered
|
|
87
|
-
Rpush::Daemon.store.mark_batch_delivered(delivered)
|
|
88
|
-
delivered.each do |notification|
|
|
104
|
+
Rpush::Daemon.store.mark_batch_delivered(@delivered)
|
|
105
|
+
@delivered.each do |notification|
|
|
89
106
|
reflect(:notification_delivered, notification)
|
|
90
107
|
end
|
|
91
|
-
delivered.clear
|
|
92
108
|
end
|
|
93
109
|
|
|
94
110
|
def complete_failed
|
|
95
|
-
failed.each do |(code, description), notifications|
|
|
111
|
+
@failed.each do |(code, description), notifications|
|
|
96
112
|
Rpush::Daemon.store.mark_batch_failed(notifications, code, description)
|
|
97
113
|
notifications.each do |notification|
|
|
98
114
|
reflect(:notification_failed, notification)
|
|
99
115
|
end
|
|
100
116
|
end
|
|
101
|
-
failed.clear
|
|
102
117
|
end
|
|
103
118
|
|
|
104
119
|
def complete_retried
|
|
105
|
-
retryable.each do |deliver_after, notifications|
|
|
120
|
+
@retryable.each do |deliver_after, notifications|
|
|
106
121
|
Rpush::Daemon.store.mark_batch_retryable(notifications, deliver_after)
|
|
107
122
|
notifications.each do |notification|
|
|
108
123
|
reflect(:notification_will_retry, notification)
|
|
109
124
|
end
|
|
110
125
|
end
|
|
111
|
-
retryable.clear
|
|
112
126
|
end
|
|
113
127
|
end
|
|
114
128
|
end
|