rapns_rails_2 3.4.3
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 +15 -0
- data/CHANGELOG.md +83 -0
- data/LICENSE +7 -0
- data/README.md +168 -0
- data/bin/rapns +37 -0
- data/config/database.yml +44 -0
- data/lib/generators/rapns_generator.rb +25 -0
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
- data/lib/generators/templates/add_app_to_rapns.rb +11 -0
- data/lib/generators/templates/add_gcm.rb +95 -0
- data/lib/generators/templates/create_rapns_apps.rb +16 -0
- data/lib/generators/templates/create_rapns_feedback.rb +15 -0
- data/lib/generators/templates/create_rapns_notifications.rb +26 -0
- data/lib/generators/templates/rapns.rb +87 -0
- data/lib/rapns/TODO +3 -0
- data/lib/rapns/apns/app.rb +25 -0
- data/lib/rapns/apns/binary_notification_validator.rb +12 -0
- data/lib/rapns/apns/device_token_format_validator.rb +12 -0
- data/lib/rapns/apns/feedback.rb +16 -0
- data/lib/rapns/apns/notification.rb +91 -0
- data/lib/rapns/apns_feedback.rb +13 -0
- data/lib/rapns/app.rb +16 -0
- data/lib/rapns/configuration.rb +89 -0
- data/lib/rapns/daemon/apns/app_runner.rb +26 -0
- data/lib/rapns/daemon/apns/certificate_expired_error.rb +20 -0
- data/lib/rapns/daemon/apns/connection.rb +142 -0
- data/lib/rapns/daemon/apns/delivery.rb +64 -0
- data/lib/rapns/daemon/apns/delivery_handler.rb +35 -0
- data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
- data/lib/rapns/daemon/apns/feedback_receiver.rb +89 -0
- data/lib/rapns/daemon/app_runner.rb +179 -0
- data/lib/rapns/daemon/batch.rb +112 -0
- data/lib/rapns/daemon/delivery.rb +23 -0
- data/lib/rapns/daemon/delivery_error.rb +19 -0
- data/lib/rapns/daemon/delivery_handler.rb +52 -0
- data/lib/rapns/daemon/delivery_handler_collection.rb +33 -0
- data/lib/rapns/daemon/feeder.rb +65 -0
- data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
- data/lib/rapns/daemon/gcm/delivery.rb +228 -0
- data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
- data/lib/rapns/daemon/interruptible_sleep.rb +65 -0
- data/lib/rapns/daemon/reflectable.rb +13 -0
- data/lib/rapns/daemon/store/active_record/reconnectable.rb +66 -0
- data/lib/rapns/daemon/store/active_record.rb +128 -0
- data/lib/rapns/daemon.rb +129 -0
- data/lib/rapns/deprecatable.rb +23 -0
- data/lib/rapns/deprecation.rb +23 -0
- data/lib/rapns/embed.rb +28 -0
- data/lib/rapns/gcm/app.rb +7 -0
- data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
- data/lib/rapns/gcm/notification.rb +37 -0
- data/lib/rapns/gcm/payload_data_size_validator.rb +13 -0
- data/lib/rapns/gcm/registration_ids_count_validator.rb +13 -0
- data/lib/rapns/logger.rb +76 -0
- data/lib/rapns/multi_json_helper.rb +16 -0
- data/lib/rapns/notification.rb +62 -0
- data/lib/rapns/notifier.rb +35 -0
- data/lib/rapns/push.rb +17 -0
- data/lib/rapns/rails-2-compatibility.rb +34 -0
- data/lib/rapns/reflection.rb +44 -0
- data/lib/rapns/upgraded.rb +31 -0
- data/lib/rapns/version.rb +3 -0
- data/lib/rapns_rails_2.rb +67 -0
- data/lib/tasks/cane.rake +18 -0
- data/lib/tasks/test.rake +38 -0
- data/spec/support/cert_with_password.pem +90 -0
- data/spec/support/cert_without_password.pem +59 -0
- data/spec/support/simplecov_helper.rb +13 -0
- data/spec/support/simplecov_quality_formatter.rb +8 -0
- data/spec/tmp/.gitkeep +0 -0
- data/spec/unit/apns/app_spec.rb +29 -0
- data/spec/unit/apns/feedback_spec.rb +9 -0
- data/spec/unit/apns/notification_spec.rb +215 -0
- data/spec/unit/apns_feedback_spec.rb +21 -0
- data/spec/unit/app_spec.rb +16 -0
- data/spec/unit/configuration_spec.rb +55 -0
- data/spec/unit/daemon/apns/app_runner_spec.rb +45 -0
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
- data/spec/unit/daemon/apns/connection_spec.rb +287 -0
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +59 -0
- data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +134 -0
- data/spec/unit/daemon/app_runner_shared.rb +83 -0
- data/spec/unit/daemon/app_runner_spec.rb +170 -0
- data/spec/unit/daemon/batch_spec.rb +219 -0
- data/spec/unit/daemon/delivery_error_spec.rb +13 -0
- data/spec/unit/daemon/delivery_handler_collection_spec.rb +37 -0
- data/spec/unit/daemon/delivery_handler_shared.rb +45 -0
- data/spec/unit/daemon/feeder_spec.rb +81 -0
- data/spec/unit/daemon/gcm/app_runner_spec.rb +19 -0
- data/spec/unit/daemon/gcm/delivery_handler_spec.rb +44 -0
- data/spec/unit/daemon/gcm/delivery_spec.rb +289 -0
- data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
- data/spec/unit/daemon/reflectable_spec.rb +27 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
- data/spec/unit/daemon/store/active_record_spec.rb +281 -0
- data/spec/unit/daemon_spec.rb +157 -0
- data/spec/unit/deprecatable_spec.rb +32 -0
- data/spec/unit/deprecation_spec.rb +15 -0
- data/spec/unit/embed_spec.rb +50 -0
- data/spec/unit/gcm/app_spec.rb +4 -0
- data/spec/unit/gcm/notification_spec.rb +52 -0
- data/spec/unit/logger_spec.rb +180 -0
- data/spec/unit/notification_shared.rb +45 -0
- data/spec/unit/notification_spec.rb +4 -0
- data/spec/unit/notifier_spec.rb +32 -0
- data/spec/unit/push_spec.rb +44 -0
- data/spec/unit/rapns_spec.rb +9 -0
- data/spec/unit/reflection_spec.rb +30 -0
- data/spec/unit/upgraded_spec.rb +40 -0
- data/spec/unit_spec_helper.rb +137 -0
- metadata +232 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class AppRunner
|
|
4
|
+
extend Reflectable
|
|
5
|
+
include Reflectable
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_reader :runners
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
@runners = {}
|
|
12
|
+
|
|
13
|
+
def self.enqueue(notifications)
|
|
14
|
+
notifications.group_by(&:app_id).each do |app_id, group|
|
|
15
|
+
batch = Batch.new(group)
|
|
16
|
+
if app = runners[app_id]
|
|
17
|
+
app.enqueue(batch)
|
|
18
|
+
else
|
|
19
|
+
Rapns.logger.error("No such app '#{app_id}' for notifications #{batch.describe}.")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.sync
|
|
25
|
+
apps = Rapns::App.all
|
|
26
|
+
apps.each { |app| sync_app(app) }
|
|
27
|
+
removed = runners.keys - apps.map(&:id)
|
|
28
|
+
removed.each { |app_id| runners.delete(app_id).stop }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.sync_app(app)
|
|
32
|
+
if runners[app.id]
|
|
33
|
+
runners[app.id].sync(app)
|
|
34
|
+
else
|
|
35
|
+
runner = new_runner(app)
|
|
36
|
+
begin
|
|
37
|
+
runner.start
|
|
38
|
+
runners[app.id] = runner
|
|
39
|
+
rescue StandardError => e
|
|
40
|
+
Rapns.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
|
41
|
+
Rapns.logger.error(e)
|
|
42
|
+
reflect(:error, e)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.new_runner(app)
|
|
48
|
+
type = app.class.parent.name.demodulize
|
|
49
|
+
"Rapns::Daemon::#{type}::AppRunner".constantize.new(app)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.stop
|
|
53
|
+
runners.values.map(&:stop)
|
|
54
|
+
runners.clear
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.debug
|
|
58
|
+
runners.values.map(&:debug)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.idle
|
|
62
|
+
runners.values.select(&:idle?)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.wait
|
|
66
|
+
sleep 0.1 while !runners.values.all?(&:idle?)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
attr_reader :app
|
|
70
|
+
attr_accessor :batch
|
|
71
|
+
|
|
72
|
+
def initialize(app)
|
|
73
|
+
@app = app
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def before_start; end
|
|
77
|
+
def after_start; end
|
|
78
|
+
def before_stop; end
|
|
79
|
+
def after_stop; end
|
|
80
|
+
|
|
81
|
+
def start
|
|
82
|
+
before_start
|
|
83
|
+
app.connections.times { handlers.push(start_handler) }
|
|
84
|
+
after_start
|
|
85
|
+
Rapns.logger.info("[#{app.name}] Started, #{handlers_str}.")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def stop
|
|
89
|
+
before_stop
|
|
90
|
+
handlers.stop
|
|
91
|
+
after_stop
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def enqueue(batch)
|
|
95
|
+
self.batch = batch
|
|
96
|
+
batch.notifications.each do |notification|
|
|
97
|
+
queue.push([notification, batch])
|
|
98
|
+
reflect(:notification_enqueued, notification)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def sync(app)
|
|
103
|
+
@app = app
|
|
104
|
+
diff = handlers.size - app.connections
|
|
105
|
+
return if diff == 0
|
|
106
|
+
if diff > 0
|
|
107
|
+
decrement_handlers(diff)
|
|
108
|
+
Rapns.logger.info("[#{app.name}] Stopped #{handlers_str(diff)}. #{handlers_str} running.")
|
|
109
|
+
else
|
|
110
|
+
increment_handlers(diff.abs)
|
|
111
|
+
Rapns.logger.info("[#{app.name}] Started #{handlers_str(diff)}. #{handlers_str} running.")
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def decrement_handlers(num)
|
|
116
|
+
num.times { handlers.pop }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def increment_handlers(num)
|
|
120
|
+
num.times { handlers.push(start_handler) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def debug
|
|
124
|
+
Rapns.logger.info <<-EOS
|
|
125
|
+
|
|
126
|
+
#{@app.name}:
|
|
127
|
+
handlers: #{num_handlers}
|
|
128
|
+
queued: #{queue_size}
|
|
129
|
+
batch size: #{batch_size}
|
|
130
|
+
batch processed: #{batch_processed}
|
|
131
|
+
idle: #{idle?}
|
|
132
|
+
EOS
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def idle?
|
|
136
|
+
batch ? batch.complete? : true
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def queue_size
|
|
140
|
+
queue.size
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def batch_size
|
|
144
|
+
batch ? batch.num_notifications : 0
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def batch_processed
|
|
148
|
+
batch ? batch.num_processed : 0
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def num_handlers
|
|
152
|
+
handlers.size
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
protected
|
|
156
|
+
|
|
157
|
+
def start_handler
|
|
158
|
+
handler = new_delivery_handler
|
|
159
|
+
handler.queue = queue
|
|
160
|
+
handler.start
|
|
161
|
+
handler
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def queue
|
|
165
|
+
@queue ||= Queue.new
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def handlers
|
|
169
|
+
@handlers ||= Rapns::Daemon::DeliveryHandlerCollection.new
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def handlers_str(count = app.connections)
|
|
173
|
+
count = count.abs
|
|
174
|
+
str = count == 1 ? 'handler' : 'handlers'
|
|
175
|
+
"#{count} #{str}"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class Batch
|
|
4
|
+
include Reflectable
|
|
5
|
+
|
|
6
|
+
attr_reader :num_processed, :notifications,
|
|
7
|
+
:delivered, :failed, :retryable
|
|
8
|
+
|
|
9
|
+
def initialize(notifications)
|
|
10
|
+
@notifications = notifications
|
|
11
|
+
@num_processed = 0
|
|
12
|
+
@delivered = []
|
|
13
|
+
@failed = {}
|
|
14
|
+
@retryable = {}
|
|
15
|
+
@mutex = Mutex.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def num_notifications
|
|
19
|
+
@notifications.size
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mark_retryable(notification, deliver_after)
|
|
23
|
+
if Rapns.config.batch_storage_updates
|
|
24
|
+
retryable[deliver_after] ||= []
|
|
25
|
+
retryable[deliver_after] << notification
|
|
26
|
+
else
|
|
27
|
+
Rapns::Daemon.store.mark_retryable(notification, deliver_after)
|
|
28
|
+
reflect(:notification_will_retry, notification)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def mark_delivered(notification)
|
|
33
|
+
if Rapns.config.batch_storage_updates
|
|
34
|
+
delivered << notification
|
|
35
|
+
else
|
|
36
|
+
Rapns::Daemon.store.mark_delivered(notification)
|
|
37
|
+
reflect(:notification_delivered, notification)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def mark_failed(notification, code, description)
|
|
42
|
+
if Rapns.config.batch_storage_updates
|
|
43
|
+
key = [code, description]
|
|
44
|
+
failed[key] ||= []
|
|
45
|
+
failed[key] << notification
|
|
46
|
+
else
|
|
47
|
+
Rapns::Daemon.store.mark_failed(notification, code, description)
|
|
48
|
+
reflect(:notification_failed, notification)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def notification_processed
|
|
53
|
+
@mutex.synchronize do
|
|
54
|
+
@num_processed += 1
|
|
55
|
+
complete if @num_processed >= @notifications.size
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def complete?
|
|
60
|
+
@complete == true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def describe
|
|
64
|
+
notifications.map(&:id).join(', ')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def complete
|
|
70
|
+
[:complete_delivered, :complete_failed, :complete_retried].each do |method|
|
|
71
|
+
begin
|
|
72
|
+
send(method)
|
|
73
|
+
rescue StandardError => e
|
|
74
|
+
Rapns.logger.error(e)
|
|
75
|
+
reflect(:error, e)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
notifications.clear
|
|
80
|
+
@complete = true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def complete_delivered
|
|
84
|
+
Rapns::Daemon.store.mark_batch_delivered(delivered)
|
|
85
|
+
delivered.each do |notification|
|
|
86
|
+
reflect(:notification_delivered, notification)
|
|
87
|
+
end
|
|
88
|
+
delivered.clear
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def complete_failed
|
|
92
|
+
failed.each do |(code, description), notifications|
|
|
93
|
+
Rapns::Daemon.store.mark_batch_failed(notifications, code, description)
|
|
94
|
+
notifications.each do |notification|
|
|
95
|
+
reflect(:notification_failed, notification)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
failed.clear
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def complete_retried
|
|
102
|
+
retryable.each do |deliver_after, notifications|
|
|
103
|
+
Rapns::Daemon.store.mark_batch_retryable(notifications, deliver_after)
|
|
104
|
+
notifications.each do |notification|
|
|
105
|
+
reflect(:notification_will_retry, notification)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
retryable.clear
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class Delivery
|
|
4
|
+
include Reflectable
|
|
5
|
+
|
|
6
|
+
def mark_retryable(notification, deliver_after)
|
|
7
|
+
@batch.mark_retryable(notification, deliver_after)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def mark_retryable_exponential(notification)
|
|
11
|
+
mark_retryable(notification, Time.now + 2 ** (notification.retries + 1))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def mark_delivered
|
|
15
|
+
@batch.mark_delivered(@notification)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def mark_failed(code, description)
|
|
19
|
+
@batch.mark_failed(@notification, code, description)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
class DeliveryError < StandardError
|
|
3
|
+
attr_reader :code, :description
|
|
4
|
+
|
|
5
|
+
def initialize(code, notification_id, description)
|
|
6
|
+
@code = code
|
|
7
|
+
@notification_id = notification_id
|
|
8
|
+
@description = description
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
message
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def message
|
|
16
|
+
"Unable to deliver notification #{@notification_id}, received error #{@code} (#{@description})"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class DeliveryHandler
|
|
4
|
+
include Reflectable
|
|
5
|
+
|
|
6
|
+
WAKEUP = :wakeup
|
|
7
|
+
|
|
8
|
+
attr_accessor :queue
|
|
9
|
+
|
|
10
|
+
def start
|
|
11
|
+
@thread = Thread.new do
|
|
12
|
+
loop do
|
|
13
|
+
handle_next_notification
|
|
14
|
+
break if @stop
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def stop
|
|
20
|
+
@stop = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def wakeup
|
|
24
|
+
queue.push(WAKEUP) if @thread
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def wait
|
|
28
|
+
@thread.join if @thread
|
|
29
|
+
stopped
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
protected
|
|
33
|
+
|
|
34
|
+
def stopped
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def handle_next_notification
|
|
38
|
+
notification, batch = queue.pop
|
|
39
|
+
return if notification == WAKEUP
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
deliver(notification, batch)
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
Rapns.logger.error(e)
|
|
45
|
+
reflect(:error, e)
|
|
46
|
+
ensure
|
|
47
|
+
batch.notification_processed
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class DeliveryHandlerCollection
|
|
4
|
+
attr_reader :handlers
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@handlers = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def push(handler)
|
|
11
|
+
@handlers << handler
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pop
|
|
15
|
+
handler = @handlers.pop
|
|
16
|
+
handler.stop
|
|
17
|
+
handler.wakeup
|
|
18
|
+
@handlers.map(&:wakeup)
|
|
19
|
+
handler.wait
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def size
|
|
23
|
+
@handlers.size
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stop
|
|
27
|
+
@handlers.map(&:stop)
|
|
28
|
+
@handlers.map(&:wakeup)
|
|
29
|
+
@handlers.map(&:wait)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Daemon
|
|
3
|
+
class Feeder
|
|
4
|
+
extend Reflectable
|
|
5
|
+
|
|
6
|
+
def self.start
|
|
7
|
+
@stop = false
|
|
8
|
+
|
|
9
|
+
if Rapns.config.embedded
|
|
10
|
+
Thread.new { feed_forever }
|
|
11
|
+
elsif Rapns.config.push
|
|
12
|
+
enqueue_notifications
|
|
13
|
+
else
|
|
14
|
+
feed_forever
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.stop
|
|
19
|
+
@stop = true
|
|
20
|
+
interrupt_sleep
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.interrupt_sleep
|
|
24
|
+
interruptible_sleeper.interrupt_sleep
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
def self.feed_forever
|
|
30
|
+
loop do
|
|
31
|
+
enqueue_notifications
|
|
32
|
+
interruptible_sleeper.sleep(Rapns.config.push_poll)
|
|
33
|
+
break if stop?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.stop?
|
|
38
|
+
@stop
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.enqueue_notifications
|
|
42
|
+
begin
|
|
43
|
+
idle = Rapns::Daemon::AppRunner.idle.map(&:app)
|
|
44
|
+
return if idle.empty?
|
|
45
|
+
notifications = Rapns::Daemon.store.deliverable_notifications(idle)
|
|
46
|
+
Rapns::Daemon::AppRunner.enqueue(notifications)
|
|
47
|
+
rescue StandardError => e
|
|
48
|
+
Rapns.logger.error(e)
|
|
49
|
+
reflect(:error, e)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.interruptible_sleeper
|
|
54
|
+
unless @interruptible_sleeper
|
|
55
|
+
@interruptible_sleeper = InterruptibleSleep.new
|
|
56
|
+
if Rapns.config.udp_wake_host && Rapns.config.udp_wake_port
|
|
57
|
+
@interruptible_sleeper.enable_wake_on_udp Rapns.config.udp_wake_host, Rapns.config.udp_wake_port
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
@interruptible_sleeper
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|