rpush 1.0.0-java → 2.0.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 +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
|