rpush 2.0.1-java → 2.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +24 -18
- data/bin/rpush +1 -42
- data/lib/generators/rpush_config_generator.rb +7 -0
- data/lib/generators/{rpush_generator.rb → rpush_migration_generator.rb} +6 -11
- data/lib/generators/templates/rpush.rb +12 -12
- data/lib/generators/templates/rpush_2_0_0_updates.rb +2 -1
- data/lib/generators/templates/rpush_2_1_0_updates.rb +11 -0
- data/lib/rpush.rb +12 -4
- data/lib/rpush/apns_feedback.rb +1 -1
- data/lib/rpush/cli.rb +133 -0
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +2 -2
- data/lib/rpush/client/active_model/apns/notification.rb +4 -1
- data/lib/rpush/client/active_model/notification.rb +0 -4
- data/lib/rpush/client/active_record/apns/notification.rb +0 -6
- data/lib/rpush/client/active_record/notification.rb +3 -2
- data/lib/rpush/client/redis/notification.rb +2 -0
- data/lib/rpush/configuration.rb +16 -24
- data/lib/rpush/daemon.rb +28 -1
- data/lib/rpush/daemon/app_runner.rb +6 -1
- data/lib/rpush/daemon/proc_title.rb +1 -1
- data/lib/rpush/daemon/signal_handler.rb +13 -3
- data/lib/rpush/daemon/store/active_record.rb +1 -1
- data/lib/rpush/deprecatable.rb +2 -1
- data/lib/rpush/embed.rb +1 -1
- data/lib/rpush/logger.rb +32 -19
- data/lib/rpush/push.rb +1 -1
- data/lib/rpush/version.rb +1 -1
- data/lib/tasks/quality.rake +1 -1
- data/lib/tasks/test.rake +12 -0
- data/spec/functional/apns_spec.rb +13 -11
- data/spec/functional_spec_helper.rb +1 -4
- data/spec/spec_helper.rb +4 -4
- data/spec/support/active_record_setup.rb +2 -1
- data/spec/unit/client/active_record/apns/notification_spec.rb +29 -3
- data/spec/unit/configuration_spec.rb +0 -7
- data/spec/unit/daemon/app_runner_spec.rb +1 -1
- data/spec/unit/daemon/signal_handler_spec.rb +1 -1
- data/spec/unit/daemon_spec.rb +1 -1
- data/spec/unit/deprecatable_spec.rb +1 -1
- data/spec/unit/logger_spec.rb +4 -4
- metadata +48 -3
@@ -3,10 +3,10 @@ module Rpush
|
|
3
3
|
module ActiveModel
|
4
4
|
module Apns
|
5
5
|
class BinaryNotificationValidator < ::ActiveModel::Validator
|
6
|
-
MAX_BYTES =
|
6
|
+
MAX_BYTES = 2048
|
7
7
|
|
8
8
|
def validate(record)
|
9
|
-
return unless record.
|
9
|
+
return unless record.payload.bytesize > MAX_BYTES
|
10
10
|
record.errors[:base] << "APN notification cannot be larger than #{MAX_BYTES} bytes. Try condensing your alert and device attributes."
|
11
11
|
end
|
12
12
|
end
|
@@ -48,6 +48,8 @@ module Rpush
|
|
48
48
|
json['aps']['alert'] = alert if alert
|
49
49
|
json['aps']['badge'] = badge if badge
|
50
50
|
json['aps']['sound'] = sound if sound
|
51
|
+
json['aps']['category'] = category if category
|
52
|
+
json['aps']['url-args'] = url_args if url_args
|
51
53
|
|
52
54
|
if data && data[CONTENT_AVAILABLE_KEY]
|
53
55
|
json['aps']['content-available'] = 1
|
@@ -63,10 +65,11 @@ module Rpush
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def to_binary(options = {})
|
68
|
+
frame_payload = payload
|
66
69
|
frame_id = options[:for_validation] ? 0 : id
|
67
70
|
frame = ""
|
68
71
|
frame << [1, 32, device_token].pack("cnH*")
|
69
|
-
frame << [2,
|
72
|
+
frame << [2, frame_payload.bytesize, frame_payload].pack("cna*")
|
70
73
|
frame << [3, 4, frame_id].pack("cnN")
|
71
74
|
frame << [4, 4, expiry || APNS_DEFAULT_EXPIRY].pack("cnN")
|
72
75
|
frame << [5, 1, priority_for_frame].pack("cnc")
|
@@ -6,12 +6,6 @@ module Rpush
|
|
6
6
|
include Deprecatable
|
7
7
|
include Rpush::Client::ActiveModel::Apns::Notification
|
8
8
|
|
9
|
-
alias_method :attributes_for_device=, :data=
|
10
|
-
alias_method :attributes_for_device, :data
|
11
|
-
|
12
|
-
deprecated(:attributes_for_device, '2.1.0', 'Use :data instead.')
|
13
|
-
deprecated(:attributes_for_device=, '2.1.0', 'Use :data instead.')
|
14
|
-
|
15
9
|
def alert=(alert)
|
16
10
|
if alert.is_a?(Hash)
|
17
11
|
write_attribute(:alert, multi_json_dump(alert))
|
@@ -7,15 +7,16 @@ module Rpush
|
|
7
7
|
|
8
8
|
self.table_name = 'rpush_notifications'
|
9
9
|
|
10
|
-
# TODO: Dump using multi json.
|
11
10
|
serialize :registration_ids
|
11
|
+
serialize :url_args
|
12
12
|
|
13
13
|
belongs_to :app, class_name: 'Rpush::Client::ActiveRecord::App'
|
14
14
|
|
15
15
|
if Rpush.attr_accessible_available?
|
16
16
|
attr_accessible :badge, :device_token, :sound, :alert, :data, :expiry, :delivered,
|
17
17
|
:delivered_at, :failed, :failed_at, :error_code, :error_description, :deliver_after,
|
18
|
-
:alert_is_json, :app, :app_id, :collapse_key, :delay_while_idle, :registration_ids,
|
18
|
+
:alert_is_json, :app, :app_id, :collapse_key, :delay_while_idle, :registration_ids,
|
19
|
+
:uri, :url_args, :category
|
19
20
|
end
|
20
21
|
|
21
22
|
def data=(attrs)
|
data/lib/rpush/configuration.rb
CHANGED
@@ -23,9 +23,10 @@ module Rpush
|
|
23
23
|
@client_initialized = true
|
24
24
|
end
|
25
25
|
|
26
|
-
CONFIG_ATTRS = [:
|
27
|
-
:
|
28
|
-
|
26
|
+
CONFIG_ATTRS = [:push_poll, :feedback_poll, :embedded, :pid_file, :batch_size,
|
27
|
+
:push, :client, :logger, :log_file, :foreground, :log_level,
|
28
|
+
# Deprecated
|
29
|
+
:log_dir]
|
29
30
|
|
30
31
|
class ConfigurationWithoutDefaults < Struct.new(*CONFIG_ATTRS)
|
31
32
|
end
|
@@ -33,8 +34,7 @@ module Rpush
|
|
33
34
|
class Configuration < Struct.new(*CONFIG_ATTRS)
|
34
35
|
include Deprecatable
|
35
36
|
|
36
|
-
deprecated(:
|
37
|
-
deprecated(:check_for_errors=, '2.1.0', 'APNs error detection is now performed asynchronously and does not require pauses.')
|
37
|
+
deprecated(:log_dir=, '2.3.0', 'Please use log_file instead.')
|
38
38
|
|
39
39
|
delegate :redis_options, :redis_options=, to: :Modis
|
40
40
|
|
@@ -52,45 +52,37 @@ module Rpush
|
|
52
52
|
|
53
53
|
def pid_file=(path)
|
54
54
|
if path && !Pathname.new(path).absolute?
|
55
|
-
super(File.join(
|
55
|
+
super(File.join(Rpush.root, path))
|
56
56
|
else
|
57
57
|
super
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
def foreground=(bool)
|
66
|
-
if Rpush.jruby?
|
67
|
-
# The JVM does not support fork().
|
68
|
-
super(true)
|
61
|
+
def log_file=(path)
|
62
|
+
if path && !Pathname.new(path).absolute?
|
63
|
+
super(File.join(Rpush.root, path))
|
69
64
|
else
|
70
65
|
super
|
71
66
|
end
|
72
67
|
end
|
73
68
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
self.foreground = true
|
78
|
-
else
|
79
|
-
self.foreground = false
|
80
|
-
end
|
69
|
+
def logger=(logger)
|
70
|
+
super(logger)
|
71
|
+
end
|
81
72
|
|
73
|
+
def set_defaults
|
82
74
|
self.push_poll = 2
|
83
75
|
self.feedback_poll = 60
|
84
76
|
self.batch_size = 100
|
85
|
-
self.pid_file = nil
|
86
77
|
self.client = :active_record
|
87
78
|
self.logger = nil
|
88
|
-
self.
|
79
|
+
self.log_file = 'log/rpush.log'
|
80
|
+
self.pid_file = 'tmp/rpush.pid'
|
81
|
+
self.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::INFO
|
89
82
|
|
90
83
|
# Internal options.
|
91
84
|
self.embedded = false
|
92
85
|
self.push = false
|
93
|
-
self.environment = Rails.env
|
94
86
|
end
|
95
87
|
end
|
96
88
|
end
|
data/lib/rpush/daemon.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
require 'thread'
|
2
4
|
require 'socket'
|
3
5
|
require 'pathname'
|
@@ -46,6 +48,8 @@ require 'rpush/daemon/adm'
|
|
46
48
|
|
47
49
|
module Rpush
|
48
50
|
module Daemon
|
51
|
+
extend Term::ANSIColor
|
52
|
+
|
49
53
|
class << self
|
50
54
|
attr_accessor :store
|
51
55
|
end
|
@@ -60,6 +64,9 @@ module Rpush
|
|
60
64
|
# No further store connections will be made from this thread.
|
61
65
|
store.release_connection
|
62
66
|
|
67
|
+
Rpush.logger.info('Rpush operational.')
|
68
|
+
show_welcome_if_needed
|
69
|
+
|
63
70
|
# Blocking call, returns after Feeder.stop is called from another thread.
|
64
71
|
Feeder.start
|
65
72
|
|
@@ -68,12 +75,19 @@ module Rpush
|
|
68
75
|
end
|
69
76
|
|
70
77
|
def self.shutdown
|
71
|
-
|
78
|
+
if Rpush.config.foreground
|
79
|
+
# Eat the '^C'
|
80
|
+
STDOUT.write("\b\b")
|
81
|
+
STDOUT.flush
|
82
|
+
end
|
83
|
+
|
84
|
+
Rpush.logger.info('Shutting down... ', true)
|
72
85
|
|
73
86
|
shutdown_lock.synchronize do
|
74
87
|
Feeder.stop
|
75
88
|
AppRunner.stop
|
76
89
|
delete_pid_file
|
90
|
+
puts green('✔') if Rpush.config.foreground
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
@@ -105,6 +119,7 @@ module Rpush
|
|
105
119
|
def self.write_pid_file
|
106
120
|
unless Rpush.config.pid_file.blank?
|
107
121
|
begin
|
122
|
+
FileUtils.mkdir_p(File.dirname(Rpush.config.pid_file))
|
108
123
|
File.open(Rpush.config.pid_file, 'w') { |f| f.puts Process.pid }
|
109
124
|
rescue SystemCallError => e
|
110
125
|
Rpush.logger.error("Failed to write PID to '#{Rpush.config.pid_file}': #{e.inspect}")
|
@@ -116,5 +131,17 @@ module Rpush
|
|
116
131
|
pid_file = Rpush.config.pid_file
|
117
132
|
File.delete(pid_file) if !pid_file.blank? && File.exist?(pid_file)
|
118
133
|
end
|
134
|
+
|
135
|
+
def self.show_welcome_if_needed
|
136
|
+
if Rpush::Daemon::AppRunner.app_ids.count == 0
|
137
|
+
puts <<-EOS
|
138
|
+
|
139
|
+
* #{green('Is this your first time using Rpush?')}
|
140
|
+
You need to create an App before you can start using Rpush.
|
141
|
+
Please refer to the documentation at https://github.com/rpush/rpush
|
142
|
+
|
143
|
+
EOS
|
144
|
+
end
|
145
|
+
end
|
119
146
|
end
|
120
147
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
module Rpush
|
2
4
|
module Daemon
|
3
5
|
class AppRunner
|
6
|
+
extend Term::ANSIColor
|
7
|
+
|
4
8
|
extend Reflectable
|
5
9
|
include Reflectable
|
6
10
|
include Loggable
|
@@ -24,9 +28,10 @@ module Rpush
|
|
24
28
|
end
|
25
29
|
|
26
30
|
def self.start_app(app)
|
31
|
+
Rpush.logger.info("[#{app.name}] Starting #{pluralize(app.connections, 'dispatcher')}... ", true)
|
27
32
|
@runners[app.id] = new(app)
|
28
33
|
@runners[app.id].start
|
29
|
-
|
34
|
+
puts green('✔') if Rpush.config.foreground
|
30
35
|
rescue StandardError => e
|
31
36
|
@runners.delete(app.id)
|
32
37
|
Rpush.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
@@ -9,7 +9,7 @@ module Rpush
|
|
9
9
|
total_dispatchers = AppRunner.total_dispatchers
|
10
10
|
dispatchers_str = total_dispatchers == 1 ? 'dispatcher' : 'dispatchers'
|
11
11
|
total_queued = AppRunner.total_queued
|
12
|
-
format("rpush | %
|
12
|
+
format("rpush | %d queued | %d %s", total_queued, total_dispatchers, dispatchers_str)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -28,10 +28,9 @@ module Rpush
|
|
28
28
|
begin
|
29
29
|
case signal
|
30
30
|
when 'HUP'
|
31
|
-
|
32
|
-
Feeder.wakeup
|
31
|
+
handle_hup
|
33
32
|
when 'USR2'
|
34
|
-
|
33
|
+
handle_usr2
|
35
34
|
when 'INT', 'TERM'
|
36
35
|
Thread.new { Rpush::Daemon.shutdown }
|
37
36
|
break
|
@@ -48,6 +47,17 @@ module Rpush
|
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
50
|
+
def self.handle_hup
|
51
|
+
Rpush.logger.info("Received HUP signal.")
|
52
|
+
Synchronizer.sync
|
53
|
+
Feeder.wakeup
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.handle_usr2
|
57
|
+
Rpush.logger.info("Received USR2 signal.")
|
58
|
+
AppRunner.debug
|
59
|
+
end
|
60
|
+
|
51
61
|
def self.trap_signals?
|
52
62
|
!Rpush.config.embedded
|
53
63
|
end
|
@@ -166,7 +166,7 @@ module Rpush
|
|
166
166
|
end
|
167
167
|
|
168
168
|
def ready_for_delivery
|
169
|
-
Rpush::Client::ActiveRecord::Notification.where('processing = ? AND delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)', false, false, false, Time.now)
|
169
|
+
Rpush::Client::ActiveRecord::Notification.where('processing = ? AND delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)', false, false, false, Time.now).order('created_at ASC')
|
170
170
|
end
|
171
171
|
|
172
172
|
def mark_processing(notifications)
|
data/lib/rpush/deprecatable.rb
CHANGED
@@ -14,7 +14,8 @@ module Rpush
|
|
14
14
|
warning << " #{msg}" if msg
|
15
15
|
class_eval(<<-RUBY, __FILE__, __LINE__)
|
16
16
|
def #{method_name}(*args, &blk)
|
17
|
-
|
17
|
+
trace = "\n\nCALLED FROM:\n" + caller.join("\n")
|
18
|
+
Rpush::Deprecation.warn(#{warning.inspect} + trace)
|
18
19
|
#{method_name_as_var}_without_warning(*args, &blk)
|
19
20
|
end
|
20
21
|
RUBY
|
data/lib/rpush/embed.rb
CHANGED
data/lib/rpush/logger.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Rpush
|
2
2
|
class Logger
|
3
3
|
def initialize
|
4
|
-
|
5
|
-
|
6
|
-
log = File.open(File.join(log_dir, 'rpush.log'), 'a')
|
4
|
+
FileUtils.mkdir_p(File.dirname(Rpush.config.log_file))
|
5
|
+
log = File.open(Rpush.config.log_file, 'a')
|
7
6
|
log.sync = true
|
8
7
|
setup_logger(log)
|
9
8
|
rescue Errno::ENOENT, Errno::EPERM => e
|
@@ -12,16 +11,16 @@ module Rpush
|
|
12
11
|
error('Logging disabled.')
|
13
12
|
end
|
14
13
|
|
15
|
-
def info(msg)
|
16
|
-
log(:info, msg)
|
14
|
+
def info(msg, inline = false)
|
15
|
+
log(:info, msg, inline)
|
17
16
|
end
|
18
17
|
|
19
|
-
def error(msg)
|
20
|
-
log(:error, msg, 'ERROR', STDERR)
|
18
|
+
def error(msg, inline = false)
|
19
|
+
log(:error, msg, inline, 'ERROR', STDERR)
|
21
20
|
end
|
22
21
|
|
23
|
-
def warn(msg)
|
24
|
-
log(:warn, msg, 'WARNING', STDERR)
|
22
|
+
def warn(msg, inline = false)
|
23
|
+
log(:warn, msg, inline, 'WARNING', STDERR)
|
25
24
|
end
|
26
25
|
|
27
26
|
private
|
@@ -30,14 +29,22 @@ module Rpush
|
|
30
29
|
if Rpush.config.logger
|
31
30
|
@logger = Rpush.config.logger
|
32
31
|
elsif ActiveSupport.const_defined?('BufferedLogger')
|
33
|
-
@logger = ActiveSupport::BufferedLogger.new(log,
|
34
|
-
@logger.auto_flushing =
|
32
|
+
@logger = ActiveSupport::BufferedLogger.new(log, Rpush.config.log_level)
|
33
|
+
@logger.auto_flushing = auto_flushing
|
35
34
|
else
|
36
|
-
@logger = ActiveSupport::Logger.new(log,
|
35
|
+
@logger = ActiveSupport::Logger.new(log, Rpush.config.log_level)
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
39
|
+
def auto_flushing
|
40
|
+
if defined?(Rails) && Rails.logger.respond_to?(:auto_flushing)
|
41
|
+
Rails.logger.auto_flushing
|
42
|
+
else
|
43
|
+
true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def log(where, msg, inline = false, prefix = nil, io = STDOUT)
|
41
48
|
if msg.is_a?(Exception)
|
42
49
|
formatted_backtrace = msg.backtrace.join("\n")
|
43
50
|
msg = "#{msg.class.name}, #{msg.message}\n#{formatted_backtrace}"
|
@@ -47,13 +54,19 @@ module Rpush
|
|
47
54
|
formatted_msg << "[#{prefix}] " if prefix
|
48
55
|
formatted_msg << msg
|
49
56
|
|
50
|
-
|
51
|
-
io.puts formatted_msg
|
52
|
-
elsif Rpush.config.foreground
|
53
|
-
io.puts formatted_msg
|
54
|
-
end
|
55
|
-
|
57
|
+
log_foreground(io, formatted_msg, inline)
|
56
58
|
@logger.send(where, formatted_msg) if @logger
|
57
59
|
end
|
60
|
+
|
61
|
+
def log_foreground(io, formatted_msg, inline)
|
62
|
+
return unless io == STDERR || Rpush.config.foreground
|
63
|
+
|
64
|
+
if inline
|
65
|
+
io.write(formatted_msg)
|
66
|
+
io.flush
|
67
|
+
else
|
68
|
+
io.puts(formatted_msg)
|
69
|
+
end
|
70
|
+
end
|
58
71
|
end
|
59
72
|
end
|
data/lib/rpush/push.rb
CHANGED
data/lib/rpush/version.rb
CHANGED