rpush 2.4.0-java → 2.6.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -1
- data/README.md +18 -8
- data/lib/generators/rpush_migration_generator.rb +1 -0
- data/lib/generators/templates/rpush.rb +8 -2
- data/lib/generators/templates/rpush_2_0_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
- data/lib/rpush/cli.rb +63 -27
- data/lib/rpush/client/active_model.rb +3 -0
- data/lib/rpush/client/active_model/apns/notification.rb +1 -1
- data/lib/rpush/client/active_model/gcm/notification.rb +1 -0
- data/lib/rpush/client/active_model/wns/app.rb +23 -0
- data/lib/rpush/client/active_model/wns/notification.rb +28 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +11 -6
- data/lib/rpush/client/active_record.rb +3 -0
- data/lib/rpush/client/active_record/notification.rb +1 -1
- data/lib/rpush/client/active_record/wns/app.rb +11 -0
- data/lib/rpush/client/active_record/wns/notification.rb +11 -0
- data/lib/rpush/client/mongoid.rb +3 -0
- data/lib/rpush/client/mongoid/apns/feedback.rb +3 -0
- data/lib/rpush/client/mongoid/notification.rb +7 -0
- data/lib/rpush/client/mongoid/wns/app.rb +14 -0
- data/lib/rpush/client/mongoid/wns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +3 -0
- data/lib/rpush/client/redis/notification.rb +1 -0
- data/lib/rpush/client/redis/wns/app.rb +14 -0
- data/lib/rpush/client/redis/wns/notification.rb +11 -0
- data/lib/rpush/configuration.rb +3 -7
- data/lib/rpush/daemon.rb +9 -0
- data/lib/rpush/daemon/apns/feedback_receiver.rb +5 -0
- data/lib/rpush/daemon/app_runner.rb +4 -5
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +47 -12
- data/lib/rpush/daemon/dispatcher_loop.rb +5 -0
- data/lib/rpush/daemon/feeder.rb +11 -0
- data/lib/rpush/daemon/gcm/delivery.rb +2 -2
- data/lib/rpush/daemon/interruptible_sleep.rb +8 -3
- data/lib/rpush/daemon/loggable.rb +4 -0
- data/lib/rpush/daemon/rpc.rb +9 -0
- data/lib/rpush/daemon/rpc/client.rb +27 -0
- data/lib/rpush/daemon/rpc/server.rb +82 -0
- data/lib/rpush/daemon/signal_handler.rb +7 -0
- data/lib/rpush/daemon/store/active_record.rb +17 -3
- data/lib/rpush/daemon/store/mongoid.rb +2 -2
- data/lib/rpush/daemon/store/redis.rb +2 -2
- data/lib/rpush/daemon/tcp_connection.rb +2 -2
- data/lib/rpush/daemon/wns.rb +9 -0
- data/lib/rpush/daemon/wns/delivery.rb +204 -0
- data/lib/rpush/embed.rb +15 -13
- data/lib/rpush/logger.rb +4 -0
- data/lib/rpush/plugin.rb +1 -1
- data/lib/rpush/push.rb +2 -11
- data/lib/rpush/reflection_collection.rb +15 -17
- data/lib/rpush/reflection_public_methods.rb +6 -4
- data/lib/rpush/version.rb +1 -1
- data/spec/functional/apns_spec.rb +1 -11
- data/spec/functional/cli_spec.rb +36 -0
- data/spec/functional_spec_helper.rb +11 -1
- data/spec/spec_helper.rb +4 -3
- data/spec/support/active_record_setup.rb +3 -2
- data/spec/unit/client/active_record/apns/notification_spec.rb +1 -1
- data/spec/unit/client/active_record/gcm/notification_spec.rb +5 -0
- data/spec/unit/configuration_spec.rb +0 -7
- data/spec/unit/daemon/adm/delivery_spec.rb +2 -2
- data/spec/unit/daemon/app_runner_spec.rb +2 -3
- data/spec/unit/daemon/gcm/delivery_spec.rb +1 -1
- data/spec/unit/daemon/tcp_connection_spec.rb +1 -1
- data/spec/unit/daemon/wns/delivery_spec.rb +171 -0
- data/spec/unit/daemon/wpns/delivery_spec.rb +1 -1
- data/spec/unit/daemon_spec.rb +2 -0
- data/spec/unit/embed_spec.rb +4 -11
- data/spec/unit/logger_spec.rb +2 -2
- data/spec/unit/push_spec.rb +0 -7
- data/spec/unit_spec_helper.rb +1 -1
- metadata +20 -2
data/lib/rpush/client/mongoid.rb
CHANGED
@@ -27,5 +27,8 @@ require 'rpush/client/mongoid/gcm/app'
|
|
27
27
|
require 'rpush/client/mongoid/wpns/notification'
|
28
28
|
require 'rpush/client/mongoid/wpns/app'
|
29
29
|
|
30
|
+
require 'rpush/client/mongoid/wns/notification'
|
31
|
+
require 'rpush/client/mongoid/wns/app'
|
32
|
+
|
30
33
|
require 'rpush/client/mongoid/adm/notification'
|
31
34
|
require 'rpush/client/mongoid/adm/app'
|
@@ -3,6 +3,7 @@ module Rpush
|
|
3
3
|
module Mongoid
|
4
4
|
class Notification
|
5
5
|
include ::Mongoid::Document
|
6
|
+
include ::Mongoid::Timestamps
|
6
7
|
include ::Mongoid::Autoinc
|
7
8
|
include Rpush::MultiJsonHelper
|
8
9
|
include Rpush::Client::ActiveModel::Notification
|
@@ -31,11 +32,17 @@ module Rpush
|
|
31
32
|
field :priority, type: Integer
|
32
33
|
field :url_args, type: Array
|
33
34
|
field :category, type: String
|
35
|
+
field :content_available, type: Boolean, default: false
|
34
36
|
|
35
37
|
field :integer_id, type: Integer
|
36
38
|
increments :integer_id, model_name: name
|
37
39
|
index integer_id: 1
|
38
40
|
|
41
|
+
index delivered: 1, failed: 1, deliver_after: 1, processing: 1
|
42
|
+
index delivered: 1, failed: 1
|
43
|
+
index device_token: 1
|
44
|
+
index app_id: 1
|
45
|
+
|
39
46
|
belongs_to :app
|
40
47
|
end
|
41
48
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module Mongoid
|
4
|
+
module Wns
|
5
|
+
class App < Rpush::Client::Mongoid::App
|
6
|
+
include Rpush::Client::ActiveModel::Wns::App
|
7
|
+
|
8
|
+
field :access_token, type: String
|
9
|
+
field :access_token_expiration, type: Time
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/rpush/client/redis.rb
CHANGED
@@ -30,6 +30,9 @@ require 'rpush/client/redis/adm/notification'
|
|
30
30
|
require 'rpush/client/redis/wpns/app'
|
31
31
|
require 'rpush/client/redis/wpns/notification'
|
32
32
|
|
33
|
+
require 'rpush/client/redis/wns/app'
|
34
|
+
require 'rpush/client/redis/wns/notification'
|
35
|
+
|
33
36
|
Modis.configure do |config|
|
34
37
|
config.namespace = :rpush
|
35
38
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module Redis
|
4
|
+
module Wns
|
5
|
+
class App < Rpush::Client::Redis::App
|
6
|
+
include Rpush::Client::ActiveModel::Wns::App
|
7
|
+
|
8
|
+
attribute :access_token, :string
|
9
|
+
attribute :access_token_expiration, :timestamp
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/rpush/configuration.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
require 'ostruct'
|
2
3
|
|
3
4
|
module Rpush
|
4
5
|
class << self
|
@@ -16,7 +17,7 @@ module Rpush
|
|
16
17
|
end
|
17
18
|
|
18
19
|
CURRENT_ATTRS = [:push_poll, :embedded, :pid_file, :batch_size, :push, :client, :logger, :log_file, :foreground, :log_level, :plugin, :apns]
|
19
|
-
DEPRECATED_ATTRS = [
|
20
|
+
DEPRECATED_ATTRS = []
|
20
21
|
CONFIG_ATTRS = CURRENT_ATTRS + DEPRECATED_ATTRS
|
21
22
|
|
22
23
|
class ConfigurationError < StandardError; end
|
@@ -97,11 +98,6 @@ module Rpush
|
|
97
98
|
Modis.redis_options = options if client == :redis
|
98
99
|
end
|
99
100
|
|
100
|
-
def feedback_poll=(frequency)
|
101
|
-
apns.feedback_receiver.frequency = frequency
|
102
|
-
end
|
103
|
-
deprecated(:feedback_poll=, '2.5.0', 'Please use apns.feedback_receiver.frequency= instead.')
|
104
|
-
|
105
101
|
def initialize_client
|
106
102
|
return if @client_initialized
|
107
103
|
raise ConfigurationError, 'Rpush.config.client is not set.' unless client
|
@@ -110,7 +106,7 @@ module Rpush
|
|
110
106
|
client_module = Rpush::Client.const_get(client.to_s.camelize)
|
111
107
|
Rpush.send(:include, client_module) unless Rpush.ancestors.include?(client_module)
|
112
108
|
|
113
|
-
[:Apns, :Gcm, :Wpns, :Adm].each do |service|
|
109
|
+
[:Apns, :Gcm, :Wpns, :Wns, :Adm].each do |service|
|
114
110
|
Rpush.const_set(service, client_module.const_get(service)) unless Rpush.const_defined?(service)
|
115
111
|
end
|
116
112
|
|
data/lib/rpush/daemon.rb
CHANGED
@@ -30,6 +30,10 @@ require 'rpush/daemon/ring_buffer'
|
|
30
30
|
require 'rpush/daemon/signal_handler'
|
31
31
|
require 'rpush/daemon/proc_title'
|
32
32
|
|
33
|
+
require 'rpush/daemon/rpc'
|
34
|
+
require 'rpush/daemon/rpc/server'
|
35
|
+
require 'rpush/daemon/rpc/client'
|
36
|
+
|
33
37
|
require 'rpush/daemon/store/interface'
|
34
38
|
|
35
39
|
require 'rpush/daemon/apns/delivery'
|
@@ -42,6 +46,9 @@ require 'rpush/daemon/gcm'
|
|
42
46
|
require 'rpush/daemon/wpns/delivery'
|
43
47
|
require 'rpush/daemon/wpns'
|
44
48
|
|
49
|
+
require 'rpush/daemon/wns/delivery'
|
50
|
+
require 'rpush/daemon/wns'
|
51
|
+
|
45
52
|
require 'rpush/daemon/adm/delivery'
|
46
53
|
require 'rpush/daemon/adm'
|
47
54
|
|
@@ -57,6 +64,7 @@ module Rpush
|
|
57
64
|
SignalHandler.start
|
58
65
|
common_init
|
59
66
|
Synchronizer.sync
|
67
|
+
Rpc::Server.start
|
60
68
|
|
61
69
|
# No further store connections will be made from this thread.
|
62
70
|
store.release_connection
|
@@ -81,6 +89,7 @@ module Rpush
|
|
81
89
|
Rpush.logger.info('Shutting down... ', true)
|
82
90
|
|
83
91
|
shutdown_lock.synchronize do
|
92
|
+
Rpc::Server.stop
|
84
93
|
Feeder.stop
|
85
94
|
AppRunner.stop
|
86
95
|
delete_pid_file
|
@@ -84,8 +84,8 @@ module Rpush
|
|
84
84
|
@runners[app.id].increment_dispatchers(num)
|
85
85
|
end
|
86
86
|
|
87
|
-
def self.
|
88
|
-
@runners.values.map(&:
|
87
|
+
def self.status
|
88
|
+
{ app_runners: @runners.values.map(&:status) }
|
89
89
|
end
|
90
90
|
|
91
91
|
attr_reader :app
|
@@ -140,7 +140,7 @@ module Rpush
|
|
140
140
|
num.times { @dispatcher_loops.push(new_dispatcher_loop) }
|
141
141
|
end
|
142
142
|
|
143
|
-
def
|
143
|
+
def status
|
144
144
|
dispatcher_details = {}
|
145
145
|
|
146
146
|
@dispatcher_loops.each_with_index do |dispatcher_loop, i|
|
@@ -151,8 +151,7 @@ module Rpush
|
|
151
151
|
}
|
152
152
|
end
|
153
153
|
|
154
|
-
|
155
|
-
log_info(JSON.pretty_generate(runner_details))
|
154
|
+
{ app_name: @app.name, dispatchers: dispatcher_details, queued: queue_size }
|
156
155
|
end
|
157
156
|
|
158
157
|
def num_dispatcher_loops
|
@@ -16,6 +16,7 @@ module Rpush
|
|
16
16
|
6 => 'Missing topic size',
|
17
17
|
7 => 'Missing payload size',
|
18
18
|
8 => 'Invalid token',
|
19
|
+
10 => 'APNs closed connection (possible maintenance)',
|
19
20
|
255 => 'None (unknown error)'
|
20
21
|
}
|
21
22
|
|
@@ -34,9 +35,21 @@ module Rpush
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def cleanup
|
38
|
+
if Rpush.config.push
|
39
|
+
# In push mode only a single batch is sent, followed my immediate shutdown.
|
40
|
+
# Allow the error receiver time to handle any errors.
|
41
|
+
@reconnect_disabled = true
|
42
|
+
sleep 1
|
43
|
+
end
|
44
|
+
|
37
45
|
@stop_error_receiver = true
|
38
46
|
super
|
39
47
|
@error_receiver_thread.join if @error_receiver_thread
|
48
|
+
rescue StandardError => e
|
49
|
+
log_error(e)
|
50
|
+
reflect(:error, e)
|
51
|
+
ensure
|
52
|
+
@error_receiver_thread = nil
|
40
53
|
end
|
41
54
|
|
42
55
|
private
|
@@ -63,12 +76,12 @@ module Rpush
|
|
63
76
|
# On Linux, select returns nil from a dropped connection.
|
64
77
|
# On OS X, Errno::EBADF is raised following a Errno::EADDRNOTAVAIL from the write call.
|
65
78
|
return unless @connection.select(SELECT_TIMEOUT)
|
66
|
-
|
67
|
-
|
79
|
+
tuple = @connection.read(ERROR_TUPLE_BYTES)
|
80
|
+
rescue *TcpConnection::TCP_ERRORS
|
81
|
+
reconnect unless @stop_error_receiver
|
68
82
|
return
|
69
83
|
end
|
70
84
|
|
71
|
-
tuple = @connection.read(ERROR_TUPLE_BYTES)
|
72
85
|
@dispatch_mutex.synchronize { handle_error_response(tuple) }
|
73
86
|
rescue StandardError => e
|
74
87
|
log_error(e)
|
@@ -82,12 +95,23 @@ module Rpush
|
|
82
95
|
handle_disconnect
|
83
96
|
end
|
84
97
|
|
85
|
-
|
86
|
-
|
98
|
+
if Rpush.config.push
|
99
|
+
# Only attempt to handle a single error in Push mode.
|
100
|
+
@stop_error_receiver = true
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
reconnect
|
87
105
|
ensure
|
88
106
|
delivered_buffer.clear
|
89
107
|
end
|
90
108
|
|
109
|
+
def reconnect
|
110
|
+
return if @reconnect_disabled
|
111
|
+
log_error("Lost connection to #{@connection.host}:#{@connection.port}, reconnecting...")
|
112
|
+
@connection.reconnect_with_rescue
|
113
|
+
end
|
114
|
+
|
91
115
|
def handle_disconnect
|
92
116
|
log_error("The APNs disconnected before any notifications could be delivered. This usually indicates you are using an invalid certificate.") if delivered_buffer.size == 0
|
93
117
|
end
|
@@ -95,22 +119,33 @@ module Rpush
|
|
95
119
|
def handle_error(code, notification_id)
|
96
120
|
notification_id = Rpush::Daemon.store.translate_integer_notification_id(notification_id)
|
97
121
|
failed_pos = delivered_buffer.index(notification_id)
|
98
|
-
description =
|
99
|
-
log_error(
|
122
|
+
description = description_for_code(code)
|
123
|
+
log_error("Notification #{notification_id} failed with error: " + description)
|
100
124
|
Rpush::Daemon.store.mark_ids_failed([notification_id], code, description, Time.now)
|
101
125
|
reflect(:notification_id_failed, @app, notification_id, code, description)
|
102
126
|
|
103
127
|
if failed_pos
|
104
128
|
retry_ids = delivered_buffer[(failed_pos + 1)..-1]
|
105
|
-
|
106
|
-
now = Time.now
|
107
|
-
Rpush::Daemon.store.mark_ids_retryable(retry_ids, now)
|
108
|
-
retry_ids.each { |id| reflect(:notification_id_will_retry, @app, id, now) }
|
109
|
-
end
|
129
|
+
retry_notification_ids(retry_ids, notification_id)
|
110
130
|
elsif delivered_buffer.size > 0
|
111
131
|
log_error("Delivery sequence unknown for notifications following #{notification_id}.")
|
112
132
|
end
|
113
133
|
end
|
134
|
+
|
135
|
+
def description_for_code(code)
|
136
|
+
APNS_ERRORS[code.to_i] ? "#{APNS_ERRORS[code.to_i]} (#{code})" : "Unknown error code #{code.inspect}. Possible Rpush bug?"
|
137
|
+
end
|
138
|
+
|
139
|
+
def retry_notification_ids(ids, notification_id)
|
140
|
+
return if ids.size == 0
|
141
|
+
|
142
|
+
now = Time.now
|
143
|
+
Rpush::Daemon.store.mark_ids_retryable(ids, now)
|
144
|
+
notifications_str = 'Notification'
|
145
|
+
notifications_str += 's' if ids.size > 1
|
146
|
+
log_warn("#{notifications_str} #{ids.join(', ')} will be retried due to the failure of notification #{notification_id}.")
|
147
|
+
ids.each { |id| reflect(:notification_id_will_retry, @app, id, now) }
|
148
|
+
end
|
114
149
|
end
|
115
150
|
end
|
116
151
|
end
|
data/lib/rpush/daemon/feeder.rb
CHANGED
@@ -2,6 +2,7 @@ module Rpush
|
|
2
2
|
module Daemon
|
3
3
|
class Feeder
|
4
4
|
extend Reflectable
|
5
|
+
extend Loggable
|
5
6
|
|
6
7
|
def self.start(push_mode = false)
|
7
8
|
self.should_stop = false
|
@@ -12,12 +13,22 @@ module Rpush
|
|
12
13
|
end
|
13
14
|
|
14
15
|
@thread.join
|
16
|
+
rescue StandardError => e
|
17
|
+
log_error(e)
|
18
|
+
reflect(:error, e)
|
19
|
+
ensure
|
20
|
+
@thread = nil
|
15
21
|
end
|
16
22
|
|
17
23
|
def self.stop
|
18
24
|
self.should_stop = true
|
19
25
|
interruptible_sleeper.stop
|
20
26
|
@thread.join if @thread
|
27
|
+
rescue StandardError => e
|
28
|
+
log_error(e)
|
29
|
+
reflect(:error, e)
|
30
|
+
ensure
|
31
|
+
@thread = nil
|
21
32
|
end
|
22
33
|
|
23
34
|
def self.wakeup
|
@@ -5,7 +5,7 @@ module Rpush
|
|
5
5
|
class Delivery < Rpush::Daemon::Delivery
|
6
6
|
include MultiJsonHelper
|
7
7
|
|
8
|
-
host = 'https://
|
8
|
+
host = 'https://gcm-http.googleapis.com'
|
9
9
|
GCM_URI = URI.parse("#{host}/gcm/send")
|
10
10
|
UNAVAILABLE_STATES = %w(Unavailable InternalServerError)
|
11
11
|
INVALID_REGISTRATION_ID_STATES = %w(InvalidRegistration MismatchSenderId NotRegistered InvalidPackageName)
|
@@ -44,7 +44,7 @@ module Rpush
|
|
44
44
|
when 503
|
45
45
|
service_unavailable(response)
|
46
46
|
else
|
47
|
-
fail Rpush::DeliveryError.new(response.code, @notification.id, Rpush::Daemon::HTTP_STATUS_CODES[response.code.to_i])
|
47
|
+
fail Rpush::DeliveryError.new(response.code.to_i, @notification.id, Rpush::Daemon::HTTP_STATUS_CODES[response.code.to_i])
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -1,17 +1,22 @@
|
|
1
|
-
require 'monitor'
|
2
|
-
|
3
1
|
module Rpush
|
4
2
|
module Daemon
|
5
3
|
class InterruptibleSleep
|
6
4
|
def sleep(duration)
|
7
5
|
@thread = Thread.new { Kernel.sleep duration }
|
8
6
|
Thread.pass
|
9
|
-
|
7
|
+
|
8
|
+
begin
|
9
|
+
@thread.join
|
10
|
+
rescue StandardError
|
11
|
+
@thread = nil
|
12
|
+
end
|
10
13
|
end
|
11
14
|
|
12
15
|
def stop
|
13
16
|
@thread.kill if @thread
|
14
17
|
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
18
|
+
ensure
|
19
|
+
@thread = nil
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|