rpush 1.0.0-java → 2.0.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 +15 -0
- data/README.md +37 -22
- data/bin/rpush +13 -4
- 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 +28 -7
- data/lib/generators/templates/rpush_2_0_0_updates.rb +42 -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_model.rb +21 -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 +22 -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/active_record.rb +19 -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 +24 -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/client/redis.rb +35 -0
- data/lib/rpush/configuration.rb +27 -6
- data/lib/rpush/daemon/adm/delivery.rb +56 -55
- data/lib/rpush/daemon/apns/delivery.rb +20 -44
- data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
- data/lib/rpush/daemon/apns.rb +6 -5
- data/lib/rpush/daemon/app_runner.rb +103 -99
- 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 +114 -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 +37 -23
- 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/retryable_error.rb +2 -0
- 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 +56 -0
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +21 -17
- data/lib/rpush/daemon/store/active_record.rb +71 -38
- data/lib/rpush/daemon/store/interface.rb +19 -0
- data/lib/rpush/daemon/store/redis.rb +149 -0
- data/lib/rpush/daemon/string_helpers.rb +15 -0
- data/lib/rpush/daemon/synchronizer.rb +60 -0
- data/lib/rpush/daemon/tcp_connection.rb +6 -11
- data/lib/rpush/daemon/wpns/delivery.rb +21 -30
- data/lib/rpush/daemon.rb +40 -60
- data/lib/rpush/deprecatable.rb +4 -3
- data/lib/rpush/deprecation.rb +7 -10
- data/lib/rpush/embed.rb +8 -3
- data/lib/rpush/logger.rb +11 -15
- data/lib/rpush/push.rb +1 -2
- data/lib/rpush/reflection.rb +8 -12
- data/lib/rpush/version.rb +1 -1
- data/lib/rpush.rb +5 -29
- data/lib/tasks/quality.rake +35 -0
- data/lib/tasks/test.rake +1 -5
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +3 -6
- data/spec/functional/apns_spec.rb +117 -24
- data/spec/functional/embed_spec.rb +20 -20
- data/spec/functional/gcm_spec.rb +4 -7
- data/spec/functional/new_app_spec.rb +59 -0
- data/spec/functional/retry_spec.rb +46 -0
- data/spec/functional/synchronization_spec.rb +68 -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 +21 -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 +66 -55
- 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 +22 -17
- data/spec/unit/daemon/app_runner_spec.rb +78 -186
- 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 +6 -24
- data/spec/unit/daemon/feeder_spec.rb +38 -39
- data/spec/unit/daemon/gcm/delivery_spec.rb +122 -101
- 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 +95 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +48 -27
- 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/wpns/delivery_spec.rb +58 -50
- data/spec/unit/daemon_spec.rb +48 -82
- data/spec/unit/embed_spec.rb +6 -4
- data/spec/unit/logger_spec.rb +35 -43
- data/spec/unit/notification_shared.rb +9 -79
- data/spec/unit/push_spec.rb +6 -10
- 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 +126 -76
- 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/daemon/dispatcher_loop_collection.rb +0 -33
- data/lib/rpush/daemon/too_many_requests_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/dispatcher_loop_collection_spec.rb +0 -37
- data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
- data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
- 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
@@ -1,60 +1,41 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
1
3
|
module Rpush
|
2
4
|
module Daemon
|
3
5
|
class InterruptibleSleep
|
4
|
-
|
5
|
-
|
6
|
-
@
|
7
|
-
@
|
6
|
+
def initialize(duration)
|
7
|
+
@duration = duration
|
8
|
+
@obj = Object.new
|
9
|
+
@obj.extend(MonitorMixin)
|
10
|
+
@condition = @obj.new_cond
|
11
|
+
@stop = false
|
8
12
|
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# @return [String,Integer] host,port of bound UDP socket.
|
14
|
-
def enable_wake_on_udp(host, port)
|
15
|
-
@udp_wakeup = UDPSocket.new
|
16
|
-
@udp_wakeup.bind(host, port)
|
17
|
-
@udp_wakeup.addr.values_at(3,1)
|
14
|
+
def sleep
|
15
|
+
return if @stop
|
16
|
+
@obj.synchronize { @condition.wait(100_000) }
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
# @return [boolean] true if the sleep was interrupted, or false
|
23
|
-
def sleep(timeout)
|
24
|
-
read_ports = [@sleep_reader]
|
25
|
-
read_ports << @udp_wakeup if @udp_wakeup
|
26
|
-
rs, = IO.select(read_ports, nil, nil, timeout) rescue nil
|
27
|
-
|
28
|
-
# consume all data on the readable io's so that our next call will wait for more data
|
29
|
-
perform_io(rs, @sleep_reader, :read_nonblock)
|
30
|
-
perform_io(rs, @udp_wakeup, :recv_nonblock)
|
31
|
-
|
32
|
-
!rs.nil? && rs.any?
|
33
|
-
end
|
19
|
+
def start
|
20
|
+
@stop = false
|
34
21
|
|
35
|
-
|
36
|
-
|
37
|
-
|
22
|
+
@thread = Thread.new do
|
23
|
+
loop do
|
24
|
+
break if @stop
|
25
|
+
Kernel.sleep(@duration)
|
26
|
+
wakeup
|
27
|
+
end
|
28
|
+
end
|
38
29
|
end
|
39
30
|
|
40
|
-
def
|
41
|
-
@
|
42
|
-
|
43
|
-
@
|
31
|
+
def stop
|
32
|
+
@stop = true
|
33
|
+
wakeup
|
34
|
+
@thread.kill if @thread
|
44
35
|
end
|
45
36
|
|
46
|
-
|
47
|
-
|
48
|
-
def perform_io(selected, io, meth)
|
49
|
-
if selected && selected.include?(io)
|
50
|
-
while true
|
51
|
-
begin
|
52
|
-
io.__send__(meth, 1)
|
53
|
-
rescue Errno::EAGAIN, IO::WaitReadable
|
54
|
-
break
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
37
|
+
def wakeup
|
38
|
+
@obj.synchronize { @condition.signal }
|
58
39
|
end
|
59
40
|
end
|
60
41
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
class ProcTitle
|
4
|
+
def self.update
|
5
|
+
$0 = proc_title
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.proc_title
|
9
|
+
total_dispatchers = AppRunner.total_dispatchers
|
10
|
+
dispatchers_str = total_dispatchers == 1 ? 'dispatcher' : 'dispatchers'
|
11
|
+
total_queued = AppRunner.total_queued
|
12
|
+
format("rpush | %s | %d queued | %d %s", Rpush.config.environment, total_queued, total_dispatchers, dispatchers_str)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,11 +2,9 @@ module Rpush
|
|
2
2
|
module Daemon
|
3
3
|
module Reflectable
|
4
4
|
def reflect(name, *args)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
Rpush.logger.error(e)
|
9
|
-
end
|
5
|
+
Rpush.reflections.__dispatch(name, *args)
|
6
|
+
rescue StandardError => e
|
7
|
+
Rpush.logger.error(e)
|
10
8
|
end
|
11
9
|
end
|
12
10
|
end
|
@@ -10,12 +10,12 @@ module Rpush
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def parse
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
return unless @header
|
14
|
+
|
15
|
+
if @header.to_s =~ /^[0-9]+$/
|
16
|
+
Time.now + @header.to_i
|
17
|
+
else
|
18
|
+
Time.httpdate(@header)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -2,17 +2,27 @@ module Rpush
|
|
2
2
|
module Daemon
|
3
3
|
module ServiceConfigMethods
|
4
4
|
DISPATCHERS = {
|
5
|
-
:
|
6
|
-
:
|
5
|
+
http: Rpush::Daemon::Dispatcher::Http,
|
6
|
+
tcp: Rpush::Daemon::Dispatcher::Tcp,
|
7
|
+
apns_tcp: Rpush::Daemon::Dispatcher::ApnsTcp
|
7
8
|
}
|
8
9
|
|
10
|
+
def batch_deliveries(value = nil)
|
11
|
+
return batch_deliveries? if value.nil?
|
12
|
+
@batch_deliveries = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def batch_deliveries?
|
16
|
+
@batch_deliveries == true
|
17
|
+
end
|
18
|
+
|
9
19
|
def dispatcher(name = nil, options = {})
|
10
20
|
@dispatcher_name = name
|
11
21
|
@dispatcher_options = options
|
12
22
|
end
|
13
23
|
|
14
24
|
def dispatcher_class
|
15
|
-
DISPATCHERS[@dispatcher_name] || (
|
25
|
+
DISPATCHERS[@dispatcher_name] || (fail NotImplementedError)
|
16
26
|
end
|
17
27
|
|
18
28
|
def delivery_class
|
@@ -23,10 +33,16 @@ module Rpush
|
|
23
33
|
dispatcher_class.new(app, delivery_class, @dispatcher_options)
|
24
34
|
end
|
25
35
|
|
26
|
-
def loops(
|
27
|
-
|
28
|
-
@loops =
|
29
|
-
|
36
|
+
def loops(classes, options = {})
|
37
|
+
classes = Array[*classes]
|
38
|
+
@loops = classes.map { |cls| [cls, options] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def loop_instances(app)
|
42
|
+
(@loops || []).map do |cls, options|
|
43
|
+
next unless options.key?(:if) ? options[:if].call : true
|
44
|
+
cls.new(app)
|
45
|
+
end.compact
|
30
46
|
end
|
31
47
|
end
|
32
48
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
class SignalHandler
|
4
|
+
class << self
|
5
|
+
attr_reader :thread
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.start
|
9
|
+
return unless trap_signals?
|
10
|
+
|
11
|
+
read_io, @write_io = IO.pipe
|
12
|
+
start_handler(read_io)
|
13
|
+
%w(INT TERM HUP USR2).each do |signal|
|
14
|
+
Signal.trap(signal) { @write_io.puts(signal) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.stop
|
19
|
+
@write_io.puts('break') if @write_io
|
20
|
+
@thread.join if @thread
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.start_handler(read_io)
|
24
|
+
@thread = Thread.new do
|
25
|
+
while readable_io = IO.select([read_io]) # rubocop:disable AssignmentInCondition
|
26
|
+
signal = readable_io.first[0].gets.strip
|
27
|
+
|
28
|
+
begin
|
29
|
+
case signal
|
30
|
+
when 'HUP'
|
31
|
+
Synchronizer.sync
|
32
|
+
Feeder.wakeup
|
33
|
+
when 'USR2'
|
34
|
+
AppRunner.debug
|
35
|
+
when 'INT', 'TERM'
|
36
|
+
Thread.new { Rpush::Daemon.shutdown }
|
37
|
+
break
|
38
|
+
when 'break'
|
39
|
+
break
|
40
|
+
else
|
41
|
+
Rpush.logger.error("Unhandled signal: #{signal}")
|
42
|
+
end
|
43
|
+
rescue StandardError => e
|
44
|
+
Rpush.logger.error("Error raised when hndling signal '#{signal}'")
|
45
|
+
Rpush.logger.error(e)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.trap_signals?
|
52
|
+
!Rpush.config.embedded
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,11 +1,15 @@
|
|
1
|
-
class PGError < StandardError; end
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class
|
1
|
+
class PGError < StandardError; end unless defined?(PGError)
|
2
|
+
module PG
|
3
|
+
class Error < StandardError; end unless defined?(::PG::Error)
|
4
|
+
end
|
5
|
+
class Mysql; class Error < StandardError; end; end unless defined?(Mysql)
|
6
|
+
module Mysql2; class Error < StandardError; end; end unless defined?(Mysql2)
|
7
|
+
module ActiveRecord
|
8
|
+
class JDBCError < StandardError; end unless defined?(::ActiveRecord::JDBCError)
|
9
|
+
end
|
6
10
|
|
7
11
|
# :nocov:
|
8
|
-
|
12
|
+
unless defined?(::SQLite3::Exception)
|
9
13
|
module SQLite3
|
10
14
|
class Exception < StandardError; end
|
11
15
|
end
|
@@ -16,19 +20,19 @@ module Rpush
|
|
16
20
|
module Store
|
17
21
|
class ActiveRecord
|
18
22
|
module Reconnectable
|
19
|
-
ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError,
|
20
|
-
Mysql2::Error, ::ActiveRecord::JDBCError,
|
23
|
+
ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError, PG::Error,
|
24
|
+
Mysql::Error, Mysql2::Error, ::ActiveRecord::JDBCError,
|
25
|
+
SQLite3::Exception, ::ActiveRecord::ConnectionTimeoutError]
|
21
26
|
|
22
27
|
def with_database_reconnect_and_retry
|
23
|
-
|
24
|
-
|
25
|
-
yield
|
26
|
-
end
|
27
|
-
rescue *ADAPTER_ERRORS => e
|
28
|
-
Rpush.logger.error(e)
|
29
|
-
database_connection_lost
|
30
|
-
retry
|
28
|
+
::ActiveRecord::Base.connection_pool.with_connection do
|
29
|
+
yield
|
31
30
|
end
|
31
|
+
rescue *ADAPTER_ERRORS => e
|
32
|
+
Rpush.logger.error(e)
|
33
|
+
sleep_to_avoid_thrashing
|
34
|
+
database_connection_lost
|
35
|
+
retry
|
32
36
|
end
|
33
37
|
|
34
38
|
def database_connection_lost
|
@@ -55,7 +59,7 @@ module Rpush
|
|
55
59
|
|
56
60
|
def check_database_is_connected
|
57
61
|
# Simply asking the adapter for the connection state is not sufficient.
|
58
|
-
Rpush::Notification.count
|
62
|
+
Rpush::Client::ActiveRecord::Notification.count
|
59
63
|
end
|
60
64
|
|
61
65
|
def sleep_to_avoid_thrashing
|
@@ -8,49 +8,66 @@ module Rpush
|
|
8
8
|
class ActiveRecord
|
9
9
|
include Reconnectable
|
10
10
|
|
11
|
-
DEFAULT_MARK_OPTIONS = {:
|
11
|
+
DEFAULT_MARK_OPTIONS = { persist: true }
|
12
12
|
|
13
|
-
def
|
13
|
+
def app(id)
|
14
|
+
Rpush::Client::ActiveRecord::App.find(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def all_apps
|
18
|
+
Rpush::Client::ActiveRecord::App.all
|
19
|
+
end
|
20
|
+
|
21
|
+
def deliverable_notifications(limit)
|
14
22
|
with_database_reconnect_and_retry do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
Rpush::Client::ActiveRecord::Notification.transaction do
|
24
|
+
relation = ready_for_delivery
|
25
|
+
relation = relation.limit(limit)
|
26
|
+
notifications = relation.lock(true).to_a
|
27
|
+
mark_processing(notifications)
|
28
|
+
notifications
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
|
22
33
|
def mark_retryable(notification, deliver_after, opts = {})
|
23
34
|
opts = DEFAULT_MARK_OPTIONS.dup.merge(opts)
|
35
|
+
notification.processing = false
|
24
36
|
notification.retries += 1
|
25
37
|
notification.deliver_after = deliver_after
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
39
|
+
return unless opts[:persist]
|
40
|
+
|
41
|
+
with_database_reconnect_and_retry do
|
42
|
+
notification.save!(validate: false)
|
31
43
|
end
|
32
44
|
end
|
33
45
|
|
34
46
|
def mark_batch_retryable(notifications, deliver_after)
|
35
47
|
ids = []
|
36
48
|
notifications.each do |n|
|
37
|
-
mark_retryable(n, deliver_after, :
|
49
|
+
mark_retryable(n, deliver_after, persist: false)
|
38
50
|
ids << n.id
|
39
51
|
end
|
52
|
+
mark_ids_retryable(ids, deliver_after)
|
53
|
+
end
|
54
|
+
|
55
|
+
def mark_ids_retryable(ids, deliver_after)
|
40
56
|
with_database_reconnect_and_retry do
|
41
|
-
Rpush::Notification.where(:
|
57
|
+
Rpush::Client::ActiveRecord::Notification.where(id: ids).update_all(['processing = ?, delivered = ?, delivered_at = ?, failed = ?, failed_at = ?, retries = retries + 1, deliver_after = ?', false, false, nil, false, nil, deliver_after])
|
42
58
|
end
|
43
59
|
end
|
44
60
|
|
45
61
|
def mark_delivered(notification, time, opts = {})
|
46
62
|
opts = DEFAULT_MARK_OPTIONS.dup.merge(opts)
|
63
|
+
notification.processing = false
|
47
64
|
notification.delivered = true
|
48
65
|
notification.delivered_at = time
|
49
66
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
67
|
+
return unless opts[:persist]
|
68
|
+
|
69
|
+
with_database_reconnect_and_retry do
|
70
|
+
notification.save!(validate: false)
|
54
71
|
end
|
55
72
|
end
|
56
73
|
|
@@ -58,16 +75,17 @@ module Rpush
|
|
58
75
|
now = Time.now
|
59
76
|
ids = []
|
60
77
|
notifications.each do |n|
|
61
|
-
mark_delivered(n, now, :
|
78
|
+
mark_delivered(n, now, persist: false)
|
62
79
|
ids << n.id
|
63
80
|
end
|
64
81
|
with_database_reconnect_and_retry do
|
65
|
-
Rpush::Notification.where(:
|
82
|
+
Rpush::Client::ActiveRecord::Notification.where(id: ids).update_all(['processing = ?, delivered = ?, delivered_at = ?', false, true, now])
|
66
83
|
end
|
67
84
|
end
|
68
85
|
|
69
86
|
def mark_failed(notification, code, description, time, opts = {})
|
70
87
|
opts = DEFAULT_MARK_OPTIONS.dup.merge(opts)
|
88
|
+
notification.processing = false
|
71
89
|
notification.delivered = false
|
72
90
|
notification.delivered_at = nil
|
73
91
|
notification.failed = true
|
@@ -75,10 +93,10 @@ module Rpush
|
|
75
93
|
notification.error_code = code
|
76
94
|
notification.error_description = description
|
77
95
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
96
|
+
return unless opts[:persist]
|
97
|
+
|
98
|
+
with_database_reconnect_and_retry do
|
99
|
+
notification.save!(validate: false)
|
82
100
|
end
|
83
101
|
end
|
84
102
|
|
@@ -86,28 +104,32 @@ module Rpush
|
|
86
104
|
now = Time.now
|
87
105
|
ids = []
|
88
106
|
notifications.each do |n|
|
89
|
-
mark_failed(n, code, description, now, :
|
107
|
+
mark_failed(n, code, description, now, persist: false)
|
90
108
|
ids << n.id
|
91
109
|
end
|
110
|
+
mark_ids_failed(ids, code, description, now)
|
111
|
+
end
|
112
|
+
|
113
|
+
def mark_ids_failed(ids, code, description, time)
|
92
114
|
with_database_reconnect_and_retry do
|
93
|
-
Rpush::Notification.where(:
|
115
|
+
Rpush::Client::ActiveRecord::Notification.where(id: ids).update_all(['processing = ?, delivered = ?, delivered_at = NULL, failed = ?, failed_at = ?, error_code = ?, error_description = ?', false, false, true, time, code, description])
|
94
116
|
end
|
95
117
|
end
|
96
118
|
|
97
119
|
def create_apns_feedback(failed_at, device_token, app)
|
98
120
|
with_database_reconnect_and_retry do
|
99
|
-
Rpush::Apns::Feedback.create!(:
|
100
|
-
|
121
|
+
Rpush::Client::ActiveRecord::Apns::Feedback.create!(failed_at: failed_at,
|
122
|
+
device_token: device_token, app_id: app.id)
|
101
123
|
end
|
102
124
|
end
|
103
125
|
|
104
126
|
def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
|
105
|
-
notification = Rpush::Gcm::Notification.new
|
127
|
+
notification = Rpush::Client::ActiveRecord::Gcm::Notification.new
|
106
128
|
create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
107
129
|
end
|
108
130
|
|
109
131
|
def create_adm_notification(attrs, data, registration_ids, deliver_after, app)
|
110
|
-
notification = Rpush::Adm::Notification.new
|
132
|
+
notification = Rpush::Client::ActiveRecord::Adm::Notification.new
|
111
133
|
create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
112
134
|
end
|
113
135
|
|
@@ -123,21 +145,15 @@ module Rpush
|
|
123
145
|
end
|
124
146
|
end
|
125
147
|
|
126
|
-
def after_daemonize
|
127
|
-
reconnect_database
|
128
|
-
end
|
129
|
-
|
130
148
|
def release_connection
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
Rpush.logger.error(e)
|
135
|
-
end
|
149
|
+
::ActiveRecord::Base.connection.close
|
150
|
+
rescue StandardError => e
|
151
|
+
Rpush.logger.error(e)
|
136
152
|
end
|
137
153
|
|
138
154
|
private
|
139
155
|
|
140
|
-
def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
156
|
+
def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable ParameterLists
|
141
157
|
with_database_reconnect_and_retry do
|
142
158
|
notification.assign_attributes(attrs)
|
143
159
|
notification.data = data
|
@@ -148,7 +164,24 @@ module Rpush
|
|
148
164
|
notification
|
149
165
|
end
|
150
166
|
end
|
167
|
+
|
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)
|
170
|
+
end
|
171
|
+
|
172
|
+
def mark_processing(notifications)
|
173
|
+
return if notifications.empty?
|
174
|
+
|
175
|
+
ids = []
|
176
|
+
notifications.each do |n|
|
177
|
+
n.processing = true
|
178
|
+
ids << n.id
|
179
|
+
end
|
180
|
+
Rpush::Client::ActiveRecord::Notification.where(id: ids).update_all(['processing = ?', true])
|
181
|
+
end
|
151
182
|
end
|
152
183
|
end
|
153
184
|
end
|
154
185
|
end
|
186
|
+
|
187
|
+
Rpush::Daemon::Store::Interface.check(Rpush::Daemon::Store::ActiveRecord)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
module Store
|
4
|
+
class Interface
|
5
|
+
PUBLIC_METHODS = [:deliverable_notifications, :mark_retryable,
|
6
|
+
:mark_batch_retryable, :mark_delivered, :mark_batch_delivered,
|
7
|
+
:mark_failed, :mark_batch_failed, :create_apns_feedback,
|
8
|
+
:create_gcm_notification, :create_adm_notification, :update_app,
|
9
|
+
:update_notification, :release_connection,
|
10
|
+
:all_apps, :app, :mark_ids_failed, :mark_ids_retryable]
|
11
|
+
|
12
|
+
def self.check(klass)
|
13
|
+
missing = PUBLIC_METHODS - klass.instance_methods.map(&:to_sym)
|
14
|
+
fail "#{klass} must implement #{missing.join(', ')}." if missing.any?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|