rapns 3.3.2-java → 3.4.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +7 -0
- data/README.md +19 -21
- data/bin/rapns +14 -13
- data/lib/generators/templates/rapns.rb +8 -4
- data/lib/rapns.rb +7 -0
- data/lib/rapns/TODO +3 -0
- data/lib/rapns/apns/feedback.rb +4 -2
- data/lib/rapns/app.rb +3 -1
- data/lib/rapns/configuration.rb +8 -1
- data/lib/rapns/daemon.rb +3 -1
- data/lib/rapns/daemon/apns/app_runner.rb +3 -2
- data/lib/rapns/daemon/apns/certificate_expired_error.rb +20 -0
- data/lib/rapns/daemon/apns/connection.rb +26 -0
- data/lib/rapns/daemon/apns/delivery.rb +2 -1
- data/lib/rapns/daemon/apns/delivery_handler.rb +2 -2
- data/lib/rapns/daemon/app_runner.rb +50 -28
- data/lib/rapns/daemon/batch.rb +100 -0
- data/lib/rapns/daemon/delivery.rb +6 -10
- data/lib/rapns/daemon/delivery_handler.rb +14 -12
- data/lib/rapns/daemon/delivery_handler_collection.rb +33 -0
- data/lib/rapns/daemon/feeder.rb +3 -5
- data/lib/rapns/daemon/gcm/delivery.rb +5 -4
- data/lib/rapns/daemon/gcm/delivery_handler.rb +2 -2
- data/lib/rapns/daemon/store/active_record.rb +23 -2
- data/lib/rapns/deprecation.rb +7 -6
- data/lib/rapns/logger.rb +1 -1
- data/lib/rapns/notification.rb +5 -3
- data/lib/rapns/reflection.rb +1 -1
- data/lib/rapns/version.rb +1 -1
- data/lib/tasks/cane.rake +1 -1
- data/lib/tasks/test.rake +8 -3
- data/spec/unit/apns/app_spec.rb +4 -4
- data/spec/unit/apns_feedback_spec.rb +1 -1
- data/spec/unit/configuration_spec.rb +12 -6
- data/spec/unit/daemon/apns/app_runner_spec.rb +6 -4
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
- data/spec/unit/daemon/apns/connection_spec.rb +46 -10
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +24 -18
- data/spec/unit/daemon/apns/delivery_spec.rb +11 -12
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +16 -16
- data/spec/unit/daemon/app_runner_shared.rb +27 -10
- data/spec/unit/daemon/app_runner_spec.rb +48 -28
- data/spec/unit/daemon/batch_spec.rb +160 -0
- data/spec/unit/daemon/delivery_handler_collection_spec.rb +37 -0
- data/spec/unit/daemon/delivery_handler_shared.rb +20 -11
- data/spec/unit/daemon/feeder_spec.rb +12 -12
- data/spec/unit/daemon/gcm/app_runner_spec.rb +4 -2
- data/spec/unit/daemon/gcm/delivery_handler_spec.rb +18 -10
- data/spec/unit/daemon/gcm/delivery_spec.rb +47 -17
- data/spec/unit/daemon/interruptible_sleep_spec.rb +3 -3
- data/spec/unit/daemon/reflectable_spec.rb +1 -1
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +1 -1
- data/spec/unit/daemon/store/active_record_spec.rb +87 -10
- data/spec/unit/daemon_spec.rb +6 -6
- data/spec/unit/deprecation_spec.rb +2 -2
- data/spec/unit/logger_spec.rb +33 -17
- data/spec/unit/notification_shared.rb +7 -3
- data/spec/unit/upgraded_spec.rb +8 -14
- data/spec/unit_spec_helper.rb +9 -1
- metadata +53 -44
- data/lib/rapns/daemon/delivery_queue.rb +0 -42
- data/lib/rapns/daemon/delivery_queue_18.rb +0 -44
- data/lib/rapns/daemon/delivery_queue_19.rb +0 -42
- data/spec/acceptance/gcm_upgrade_spec.rb +0 -34
- data/spec/acceptance_spec_helper.rb +0 -85
- data/spec/unit/daemon/delivery_queue_spec.rb +0 -29
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
### 3.4.0 (Aug 28, 2013)
|
2
|
+
* Rails 4 support.
|
3
|
+
* Add apns_certificate_will_expire reflection.
|
4
|
+
* Perform storage update in batches where possible, to increase throughput.
|
5
|
+
* airbrake_notify is now deprecated, use the Reflection API instead.
|
6
|
+
* Fix calling the notification_delivered reflection twice (#149).
|
7
|
+
|
1
8
|
## 3.3.2 (June 30, 2013)
|
2
9
|
* Fix Rails 3.0.x compatibility (#138) (@yoppi).
|
3
10
|
* Ensure Rails does not set a default value for text columns (#137).
|
data/README.md
CHANGED
@@ -4,19 +4,16 @@
|
|
4
4
|
### Rapns - Professional grade APNs and GCM for Ruby.
|
5
5
|
|
6
6
|
* Supports both APNs (iOS) and GCM (Google Cloud Messaging, Android).
|
7
|
-
* Seamless Rails integration.
|
8
|
-
* Scalable - choose the number of
|
7
|
+
* Seamless Rails (3, 4) integration.
|
8
|
+
* Scalable - choose the number of persistent connections for each app.
|
9
9
|
* Designed for uptime - signal -HUP to add, update apps.
|
10
10
|
* Stable - reconnects database and network connections when lost.
|
11
|
-
* Run as a daemon or inside an existing
|
11
|
+
* Run as a daemon or inside an [existing processs](https://github.com/ileitch/rapns/wiki/Embedding-API).
|
12
12
|
* Use in a scheduler for low-workload deployments ([Push API](https://github.com/ileitch/rapns/wiki/Push-API)).
|
13
|
-
* Reflection API for fine-grained instrumentation ([Reflection API](https://github.com/ileitch/rapns/wiki/
|
13
|
+
* Reflection API for fine-grained instrumentation and error handling ([Reflection API](https://github.com/ileitch/rapns/wiki/Reflection-API)).
|
14
14
|
* Works with MRI, JRuby, Rubinius 1.8 and 1.9.
|
15
|
-
* [Airbrake](http://airbrakeapp.com/) integration.
|
16
15
|
* Built with love.
|
17
16
|
|
18
|
-
#### 2.x users please read [upgrading from 2.x to 3.0](https://github.com/ileitch/rapns/wiki/Upgrading-from-version-2.x-to-3.0)
|
19
|
-
|
20
17
|
### Who uses Rapns?
|
21
18
|
|
22
19
|
[GateGuru](http://gateguruapp.com) and [Desk.com](http://desk.com), among others!
|
@@ -34,7 +31,7 @@ Generate the migrations, rapns.yml and migrate:
|
|
34
31
|
rails g rapns
|
35
32
|
rake db:migrate
|
36
33
|
|
37
|
-
## Create an App
|
34
|
+
## Create an App & Notification
|
38
35
|
|
39
36
|
#### APNs
|
40
37
|
|
@@ -44,24 +41,12 @@ If this is your first time using the APNs, you will need to generate SSL certifi
|
|
44
41
|
app = Rapns::Apns::App.new
|
45
42
|
app.name = "ios_app"
|
46
43
|
app.certificate = File.read("/path/to/sandbox.pem")
|
47
|
-
app.environment = "sandbox"
|
44
|
+
app.environment = "sandbox" # APNs environment.
|
48
45
|
app.password = "certificate password"
|
49
46
|
app.connections = 1
|
50
47
|
app.save!
|
51
48
|
```
|
52
49
|
|
53
|
-
#### GCM
|
54
|
-
```ruby
|
55
|
-
app = Rapns::Gcm::App.new
|
56
|
-
app.name = "android_app"
|
57
|
-
app.auth_key = "..."
|
58
|
-
app.connections = 1
|
59
|
-
app.save!
|
60
|
-
```
|
61
|
-
|
62
|
-
## Create a Notification
|
63
|
-
|
64
|
-
#### APNs
|
65
50
|
```ruby
|
66
51
|
n = Rapns::Apns::Notification.new
|
67
52
|
n.app = Rapns::Apns::App.find_by_name("ios_app")
|
@@ -71,7 +56,18 @@ n.attributes_for_device = {:foo => :bar}
|
|
71
56
|
n.save!
|
72
57
|
```
|
73
58
|
|
59
|
+
You should also implement the [apns_certificate_will_expire](https://github.com/ileitch/rapns/wiki/Reflection-API) reflection to monitor when your certificate is due to expire.
|
60
|
+
|
74
61
|
#### GCM
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
app = Rapns::Gcm::App.new
|
65
|
+
app.name = "android_app"
|
66
|
+
app.auth_key = "..."
|
67
|
+
app.connections = 1
|
68
|
+
app.save!
|
69
|
+
```
|
70
|
+
|
75
71
|
```ruby
|
76
72
|
n = Rapns::Gcm::Notification.new
|
77
73
|
n.app = Rapns::Gcm::App.find_by_name("android_app")
|
@@ -80,6 +76,8 @@ n.data = {:message => "hi mom!"}
|
|
80
76
|
n.save!
|
81
77
|
```
|
82
78
|
|
79
|
+
GCM also requires you to respond to [Canonical IDs](https://github.com/ileitch/rapns/wiki/Canonical-IDs).
|
80
|
+
|
83
81
|
## Starting Rapns
|
84
82
|
|
85
83
|
As a daemon:
|
data/bin/rapns
CHANGED
@@ -5,28 +5,29 @@ require 'rapns'
|
|
5
5
|
|
6
6
|
environment = ARGV[0]
|
7
7
|
|
8
|
-
banner = 'Usage: rapns <Rails environment> [options]'
|
9
|
-
if environment.nil? || environment =~ /^-/
|
10
|
-
puts banner
|
11
|
-
exit 1
|
12
|
-
end
|
13
|
-
|
14
8
|
config = Rapns::ConfigurationWithoutDefaults.new
|
15
9
|
|
16
|
-
ARGV.options do |opts|
|
17
|
-
opts.banner =
|
10
|
+
options = ARGV.options do |opts|
|
11
|
+
opts.banner = 'Usage: rapns <Rails environment> [options]'
|
18
12
|
opts.on('-f', '--foreground', 'Run in the foreground.') { config.foreground = true }
|
19
|
-
opts.on('-P N', '--db-poll N', Integer, "Frequency in seconds to check for new notifications.
|
20
|
-
opts.on('-F N', '--feedback-poll N', Integer, "Frequency in seconds to check for feedback.
|
13
|
+
opts.on('-P N', '--db-poll N', Integer, "Frequency in seconds to check for new notifications.") { |n| config.push_poll = n }
|
14
|
+
opts.on('-F N', '--feedback-poll N', Integer, "Frequency in seconds to check for feedback.") { |n| config.feedback_poll = n }
|
21
15
|
opts.on('-e', '--no-error-checks', 'Disable APNs error checking after notification delivery.') { config.check_for_errors = false }
|
22
16
|
opts.on('-n', '--no-airbrake-notify', 'Disables error notifications via Airbrake.') { config.airbrake_notify = false }
|
23
17
|
opts.on('-p PATH', '--pid-file PATH', String, 'Path to write PID file. Relative to Rails root unless absolute.') { |path| config.pid_file = path }
|
24
|
-
opts.on('-b N', '--batch-size N', Integer, '
|
25
|
-
opts.on('-
|
18
|
+
opts.on('-b N', '--batch-size N', Integer, 'Storage backend notification batch size.') { |n| config.batch_size = n }
|
19
|
+
opts.on('-B', '--[no-]batch-storage-updates', 'Perform storage updates in batches.') { |v| config.batch_storage_updates = v }
|
20
|
+
opts.on('-v', '--version', 'Print the version.') { puts "rapns #{Rapns::VERSION}"; exit }
|
26
21
|
opts.on('-h', '--help', 'You\'re looking at it.') { puts opts; exit }
|
27
|
-
opts.parse!
|
28
22
|
end
|
29
23
|
|
24
|
+
if environment.nil? || environment =~ /^-/
|
25
|
+
puts options.to_s
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
options.parse!
|
30
|
+
|
30
31
|
ENV['RAILS_ENV'] = environment
|
31
32
|
load 'config/environment.rb'
|
32
33
|
load 'config/initializers/rapns.rb' if File.exist?('config/initializers/rapns.rb')
|
@@ -11,15 +11,15 @@
|
|
11
11
|
# Frequency in seconds to check for feedback
|
12
12
|
# config.feedback_poll = 60
|
13
13
|
|
14
|
-
# Enable/Disable error notifications via Airbrake.
|
15
|
-
# config.airbrake_notify = true
|
16
|
-
|
17
14
|
# Disable APNs error checking after notification delivery.
|
18
15
|
# config.check_for_errors = true
|
19
16
|
|
20
17
|
# ActiveRecord notifications batch size.
|
21
18
|
# config.batch_size = 5000
|
22
19
|
|
20
|
+
# Perform updates to the storage backend in batches to reduce IO.
|
21
|
+
# config.batch_storage_updates = true
|
22
|
+
|
23
23
|
# Path to write PID file. Relative to Rails root unless absolute.
|
24
24
|
# config.pid_file = '/path/to/rapns.pid'
|
25
25
|
|
@@ -71,8 +71,12 @@ Rapns.reflect do |on|
|
|
71
71
|
# on.gcm_canonical_id do |old_id, canonical_id|
|
72
72
|
# end
|
73
73
|
|
74
|
+
# Called when an APNs certificate will expire within 1 month.
|
75
|
+
# Implement on.error to catch errors raised when the certificate expires.
|
76
|
+
# on.apns_certificate_will_expire do |app, expiration_time|
|
77
|
+
# end
|
78
|
+
|
74
79
|
# Called when an exception is raised.
|
75
80
|
# on.error do |error|
|
76
81
|
# end
|
77
|
-
|
78
82
|
end
|
data/lib/rapns.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'multi_json'
|
3
3
|
|
4
|
+
module Rapns
|
5
|
+
def self.attr_accessible_available?
|
6
|
+
require 'rails'
|
7
|
+
::Rails::VERSION::STRING < '4'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
4
11
|
require 'rapns/version'
|
5
12
|
require 'rapns/deprecation'
|
6
13
|
require 'rapns/deprecatable'
|
data/lib/rapns/TODO
ADDED
data/lib/rapns/apns/feedback.rb
CHANGED
@@ -3,7 +3,9 @@ module Rapns
|
|
3
3
|
class Feedback < ActiveRecord::Base
|
4
4
|
self.table_name = 'rapns_feedback'
|
5
5
|
|
6
|
-
|
6
|
+
if Rapns.attr_accessible_available?
|
7
|
+
attr_accessible :device_token, :failed_at, :app
|
8
|
+
end
|
7
9
|
|
8
10
|
validates :device_token, :presence => true
|
9
11
|
validates :failed_at, :presence => true
|
@@ -11,4 +13,4 @@ module Rapns
|
|
11
13
|
validates_with Rapns::Apns::DeviceTokenFormatValidator
|
12
14
|
end
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end
|
data/lib/rapns/app.rb
CHANGED
@@ -2,7 +2,9 @@ module Rapns
|
|
2
2
|
class App < ActiveRecord::Base
|
3
3
|
self.table_name = 'rapns_apps'
|
4
4
|
|
5
|
-
|
5
|
+
if Rapns.attr_accessible_available?
|
6
|
+
attr_accessible :name, :environment, :certificate, :password, :connections, :auth_key
|
7
|
+
end
|
6
8
|
|
7
9
|
has_many :notifications, :class_name => 'Rapns::Notification'
|
8
10
|
|
data/lib/rapns/configuration.rb
CHANGED
@@ -9,7 +9,7 @@ module Rapns
|
|
9
9
|
|
10
10
|
CONFIG_ATTRS = [:foreground, :push_poll, :feedback_poll, :embedded,
|
11
11
|
:airbrake_notify, :check_for_errors, :pid_file, :batch_size,
|
12
|
-
:push, :store, :logger]
|
12
|
+
:push, :store, :logger, :batch_storage_updates]
|
13
13
|
|
14
14
|
class ConfigurationWithoutDefaults < Struct.new(*CONFIG_ATTRS)
|
15
15
|
end
|
@@ -31,6 +31,11 @@ module Rapns
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def airbrake_notify=(bool)
|
35
|
+
Rapns::Deprecation.warn("airbrake_notify is deprecated. Please use the Rapns.reflect API instead.")
|
36
|
+
super(bool)
|
37
|
+
end
|
38
|
+
|
34
39
|
def pid_file=(path)
|
35
40
|
if path && !Pathname.new(path).absolute?
|
36
41
|
super(File.join(Rails.root, path))
|
@@ -67,6 +72,7 @@ module Rapns
|
|
67
72
|
|
68
73
|
self.push_poll = 2
|
69
74
|
self.feedback_poll = 60
|
75
|
+
Rapns::Deprecation.muted { self.airbrake_notify = true }
|
70
76
|
self.airbrake_notify = true
|
71
77
|
self.check_for_errors = true
|
72
78
|
self.batch_size = 5000
|
@@ -74,6 +80,7 @@ module Rapns
|
|
74
80
|
self.apns_feedback_callback = nil
|
75
81
|
self.store = :active_record
|
76
82
|
self.logger = nil
|
83
|
+
self.batch_storage_updates = true
|
77
84
|
|
78
85
|
# Internal options.
|
79
86
|
self.embedded = false
|
data/lib/rapns/daemon.rb
CHANGED
@@ -9,13 +9,15 @@ require 'rapns/daemon/reflectable'
|
|
9
9
|
require 'rapns/daemon/interruptible_sleep'
|
10
10
|
require 'rapns/daemon/delivery_error'
|
11
11
|
require 'rapns/daemon/delivery'
|
12
|
-
require 'rapns/daemon/delivery_queue'
|
13
12
|
require 'rapns/daemon/feeder'
|
13
|
+
require 'rapns/daemon/batch'
|
14
14
|
require 'rapns/daemon/app_runner'
|
15
15
|
require 'rapns/daemon/delivery_handler'
|
16
|
+
require 'rapns/daemon/delivery_handler_collection'
|
16
17
|
|
17
18
|
require 'rapns/daemon/apns/delivery'
|
18
19
|
require 'rapns/daemon/apns/disconnection_error'
|
20
|
+
require 'rapns/daemon/apns/certificate_expired_error'
|
19
21
|
require 'rapns/daemon/apns/connection'
|
20
22
|
require 'rapns/daemon/apns/app_runner'
|
21
23
|
require 'rapns/daemon/apns/delivery_handler'
|
@@ -2,9 +2,10 @@ module Rapns
|
|
2
2
|
module Daemon
|
3
3
|
module Apns
|
4
4
|
class AppRunner < Rapns::Daemon::AppRunner
|
5
|
+
|
5
6
|
protected
|
6
7
|
|
7
|
-
def
|
8
|
+
def after_start
|
8
9
|
unless Rapns.config.push
|
9
10
|
poll = Rapns.config.feedback_poll
|
10
11
|
@feedback_receiver = FeedbackReceiver.new(app, poll)
|
@@ -12,7 +13,7 @@ module Rapns
|
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
+
def after_stop
|
16
17
|
@feedback_receiver.stop if @feedback_receiver
|
17
18
|
end
|
18
19
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rapns
|
2
|
+
module Apns
|
3
|
+
class CertificateExpiredError < StandardError
|
4
|
+
attr_reader :app, :time
|
5
|
+
|
6
|
+
def initialize(app, time)
|
7
|
+
@app = app
|
8
|
+
@time = time
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
message
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
"#{app.name} certificate expired at #{time}."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -101,6 +101,8 @@ module Rapns
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def connect_socket
|
104
|
+
check_certificate_expiration
|
105
|
+
|
104
106
|
tcp_socket = TCPSocket.new(@host, @port)
|
105
107
|
tcp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
106
108
|
tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
@@ -110,6 +112,30 @@ module Rapns
|
|
110
112
|
Rapns.logger.info("[#{@app.name}] Connected to #{@host}:#{@port}")
|
111
113
|
[tcp_socket, ssl_socket]
|
112
114
|
end
|
115
|
+
|
116
|
+
def check_certificate_expiration
|
117
|
+
cert = @ssl_context.cert
|
118
|
+
if certificate_expired?
|
119
|
+
Rapns.logger.error(certificate_msg('expired'))
|
120
|
+
raise Rapns::Apns::CertificateExpiredError.new(@app, cert.not_after)
|
121
|
+
elsif certificate_expires_soon?
|
122
|
+
Rapns.logger.warn(certificate_msg('will expire'))
|
123
|
+
reflect(:apns_certificate_will_expire, @app, cert.not_after)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def certificate_msg(msg)
|
128
|
+
time = @ssl_context.cert.not_after.utc.strftime("%Y-%m-%d %H:%M:%S %Z")
|
129
|
+
"[#{@app.name}] Certificate #{msg} at #{time}."
|
130
|
+
end
|
131
|
+
|
132
|
+
def certificate_expired?
|
133
|
+
@ssl_context.cert.not_after && @ssl_context.cert.not_after.utc < Time.now.utc
|
134
|
+
end
|
135
|
+
|
136
|
+
def certificate_expires_soon?
|
137
|
+
@ssl_context.cert.not_after && @ssl_context.cert.not_after.utc < (Time.now + 1.month).utc
|
138
|
+
end
|
113
139
|
end
|
114
140
|
end
|
115
141
|
end
|
@@ -16,10 +16,11 @@ module Rapns
|
|
16
16
|
255 => "None (unknown error)"
|
17
17
|
}
|
18
18
|
|
19
|
-
def initialize(app, conneciton, notification)
|
19
|
+
def initialize(app, conneciton, notification, batch)
|
20
20
|
@app = app
|
21
21
|
@connection = conneciton
|
22
22
|
@notification = notification
|
23
|
+
@batch = batch
|
23
24
|
end
|
24
25
|
|
25
26
|
def perform
|
@@ -13,8 +13,8 @@ module Rapns
|
|
13
13
|
@host, @port = HOSTS[@app.environment.to_sym]
|
14
14
|
end
|
15
15
|
|
16
|
-
def deliver(notification)
|
17
|
-
Rapns::Daemon::Apns::Delivery.
|
16
|
+
def deliver(notification, batch)
|
17
|
+
Rapns::Daemon::Apns::Delivery.new(@app, connection, notification, batch).perform
|
18
18
|
end
|
19
19
|
|
20
20
|
def stopped
|
@@ -1,17 +1,23 @@
|
|
1
1
|
module Rapns
|
2
2
|
module Daemon
|
3
3
|
class AppRunner
|
4
|
+
extend Reflectable
|
5
|
+
include Reflectable
|
6
|
+
|
4
7
|
class << self
|
5
8
|
attr_reader :runners
|
6
9
|
end
|
7
10
|
|
8
11
|
@runners = {}
|
9
12
|
|
10
|
-
def self.enqueue(
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
@@ -33,6 +39,7 @@ module Rapns
|
|
33
39
|
rescue StandardError => e
|
34
40
|
Rapns.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
35
41
|
Rapns.logger.error(e)
|
42
|
+
reflect(:error, e)
|
36
43
|
end
|
37
44
|
end
|
38
45
|
end
|
@@ -60,31 +67,36 @@ module Rapns
|
|
60
67
|
end
|
61
68
|
|
62
69
|
attr_reader :app
|
70
|
+
attr_accessor :batch
|
63
71
|
|
64
72
|
def initialize(app)
|
65
73
|
@app = app
|
66
74
|
end
|
67
75
|
|
68
|
-
def
|
69
|
-
end
|
70
|
-
|
71
|
-
def
|
72
|
-
end
|
76
|
+
def before_start; end
|
77
|
+
def after_start; end
|
78
|
+
def before_stop; end
|
79
|
+
def after_stop; end
|
73
80
|
|
74
81
|
def start
|
75
|
-
|
76
|
-
|
82
|
+
before_start
|
83
|
+
app.connections.times { handlers.push(start_handler) }
|
84
|
+
after_start
|
77
85
|
Rapns.logger.info("[#{app.name}] Started, #{handlers_str}.")
|
78
86
|
end
|
79
87
|
|
80
88
|
def stop
|
81
|
-
|
82
|
-
|
83
|
-
|
89
|
+
before_stop
|
90
|
+
handlers.stop
|
91
|
+
after_stop
|
84
92
|
end
|
85
93
|
|
86
|
-
def enqueue(
|
87
|
-
|
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
|
88
100
|
end
|
89
101
|
|
90
102
|
def sync(app)
|
@@ -92,20 +104,20 @@ module Rapns
|
|
92
104
|
diff = handlers.size - app.connections
|
93
105
|
return if diff == 0
|
94
106
|
if diff > 0
|
95
|
-
diff
|
96
|
-
Rapns.logger.info("[#{app.name}] Stopped #{handlers_str(diff)}. #{handlers_str}
|
107
|
+
decrement_handlers(diff)
|
108
|
+
Rapns.logger.info("[#{app.name}] Stopped #{handlers_str(diff)}. #{handlers_str} running.")
|
97
109
|
else
|
98
|
-
diff.abs
|
99
|
-
Rapns.logger.info("[#{app.name}] Started #{handlers_str(diff)}. #{handlers_str}
|
110
|
+
increment_handlers(diff.abs)
|
111
|
+
Rapns.logger.info("[#{app.name}] Started #{handlers_str(diff)}. #{handlers_str} running.")
|
100
112
|
end
|
101
113
|
end
|
102
114
|
|
103
|
-
def decrement_handlers
|
104
|
-
handlers.pop
|
115
|
+
def decrement_handlers(num)
|
116
|
+
num.times { handlers.pop }
|
105
117
|
end
|
106
118
|
|
107
|
-
def increment_handlers
|
108
|
-
|
119
|
+
def increment_handlers(num)
|
120
|
+
num.times { handlers.push(start_handler) }
|
109
121
|
end
|
110
122
|
|
111
123
|
def debug
|
@@ -114,18 +126,28 @@ module Rapns
|
|
114
126
|
#{@app.name}:
|
115
127
|
handlers: #{num_handlers}
|
116
128
|
queued: #{queue_size}
|
129
|
+
batch size: #{batch_size}
|
130
|
+
batch processed: #{batch_processed}
|
117
131
|
idle: #{idle?}
|
118
132
|
EOS
|
119
133
|
end
|
120
134
|
|
121
135
|
def idle?
|
122
|
-
|
136
|
+
batch ? batch.complete? : true
|
123
137
|
end
|
124
138
|
|
125
139
|
def queue_size
|
126
140
|
queue.size
|
127
141
|
end
|
128
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
|
+
|
129
151
|
def num_handlers
|
130
152
|
handlers.size
|
131
153
|
end
|
@@ -140,11 +162,11 @@ module Rapns
|
|
140
162
|
end
|
141
163
|
|
142
164
|
def queue
|
143
|
-
@queue ||=
|
165
|
+
@queue ||= Queue.new
|
144
166
|
end
|
145
167
|
|
146
168
|
def handlers
|
147
|
-
@
|
169
|
+
@handlers ||= Rapns::Daemon::DeliveryHandlerCollection.new
|
148
170
|
end
|
149
171
|
|
150
172
|
def handlers_str(count = app.connections)
|