rpush 1.0.0 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +12 -14
  4. data/bin/rpush +11 -2
  5. data/lib/generators/rpush_generator.rb +2 -0
  6. data/lib/generators/templates/add_adm.rb +5 -5
  7. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
  8. data/lib/generators/templates/add_app_to_rapns.rb +2 -2
  9. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
  10. data/lib/generators/templates/add_gcm.rb +32 -32
  11. data/lib/generators/templates/add_rpush.rb +67 -67
  12. data/lib/generators/templates/add_wpns.rb +2 -2
  13. data/lib/generators/templates/create_rapns_apps.rb +5 -5
  14. data/lib/generators/templates/create_rapns_feedback.rb +2 -2
  15. data/lib/generators/templates/create_rapns_notifications.rb +15 -15
  16. data/lib/generators/templates/rpush.rb +10 -7
  17. data/lib/generators/templates/rpush_2_0_0_updates.rb +23 -0
  18. data/lib/rpush.rb +4 -28
  19. data/lib/rpush/client/active_model.rb +21 -0
  20. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  21. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  22. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  23. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  24. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  25. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  26. data/lib/rpush/client/active_model/apns/notification.rb +90 -0
  27. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  28. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  29. data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
  30. data/lib/rpush/client/active_model/notification.rb +26 -0
  31. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  32. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  33. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  34. data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
  35. data/lib/rpush/client/active_record.rb +19 -0
  36. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  37. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  38. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  39. data/lib/rpush/client/active_record/apns/feedback.rb +20 -0
  40. data/lib/rpush/client/active_record/apns/notification.rb +46 -0
  41. data/lib/rpush/client/active_record/app.rb +17 -0
  42. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  43. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  44. data/lib/rpush/client/active_record/notification.rb +38 -0
  45. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  46. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  47. data/lib/rpush/client/redis.rb +35 -0
  48. data/lib/rpush/client/redis/adm/app.rb +14 -0
  49. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  50. data/lib/rpush/client/redis/apns/app.rb +11 -0
  51. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  52. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  53. data/lib/rpush/client/redis/app.rb +22 -0
  54. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  55. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  56. data/lib/rpush/client/redis/notification.rb +68 -0
  57. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  58. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  59. data/lib/rpush/configuration.rb +27 -6
  60. data/lib/rpush/daemon.rb +36 -56
  61. data/lib/rpush/daemon/adm/delivery.rb +50 -52
  62. data/lib/rpush/daemon/apns.rb +6 -5
  63. data/lib/rpush/daemon/apns/delivery.rb +20 -44
  64. data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
  65. data/lib/rpush/daemon/app_runner.rb +67 -60
  66. data/lib/rpush/daemon/batch.rb +54 -40
  67. data/lib/rpush/daemon/delivery.rb +13 -3
  68. data/lib/rpush/daemon/delivery_error.rb +10 -2
  69. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +106 -0
  70. data/lib/rpush/daemon/dispatcher/http.rb +3 -3
  71. data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
  72. data/lib/rpush/daemon/dispatcher_loop.rb +15 -6
  73. data/lib/rpush/daemon/errors.rb +18 -0
  74. data/lib/rpush/daemon/feeder.rb +28 -39
  75. data/lib/rpush/daemon/gcm/delivery.rb +19 -20
  76. data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
  77. data/lib/rpush/daemon/loggable.rb +2 -4
  78. data/lib/rpush/daemon/proc_title.rb +16 -0
  79. data/lib/rpush/daemon/queue_payload.rb +12 -0
  80. data/lib/rpush/daemon/reflectable.rb +3 -5
  81. data/lib/rpush/daemon/retry_header_parser.rb +6 -6
  82. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  83. data/lib/rpush/daemon/service_config_methods.rb +23 -7
  84. data/lib/rpush/daemon/signal_handler.rb +51 -0
  85. data/lib/rpush/daemon/store/active_record.rb +71 -38
  86. data/lib/rpush/daemon/store/active_record/reconnectable.rb +15 -15
  87. data/lib/rpush/daemon/store/interface.rb +19 -0
  88. data/lib/rpush/daemon/store/redis.rb +149 -0
  89. data/lib/rpush/daemon/tcp_connection.rb +6 -11
  90. data/lib/rpush/daemon/wpns/delivery.rb +21 -30
  91. data/lib/rpush/deprecatable.rb +4 -3
  92. data/lib/rpush/deprecation.rb +7 -10
  93. data/lib/rpush/embed.rb +7 -2
  94. data/lib/rpush/logger.rb +11 -15
  95. data/lib/rpush/push.rb +0 -1
  96. data/lib/rpush/reflection.rb +6 -12
  97. data/lib/rpush/version.rb +1 -1
  98. data/lib/tasks/quality.rake +34 -0
  99. data/spec/.rubocop.yml +4 -0
  100. data/spec/functional/adm_spec.rb +3 -6
  101. data/spec/functional/apns_spec.rb +118 -24
  102. data/spec/functional/embed_spec.rb +22 -20
  103. data/spec/functional/gcm_spec.rb +4 -7
  104. data/spec/functional/new_app_spec.rb +61 -0
  105. data/spec/functional/retry_spec.rb +46 -0
  106. data/spec/functional/wpns_spec.rb +3 -6
  107. data/spec/functional_spec_helper.rb +26 -0
  108. data/spec/integration/rpush_spec.rb +13 -0
  109. data/spec/integration/support/gcm_success_response.json +1 -0
  110. data/spec/spec_helper.rb +60 -0
  111. data/spec/support/active_record_setup.rb +48 -0
  112. data/{config → spec/support/config}/database.yml +0 -0
  113. data/spec/support/install.sh +43 -7
  114. data/spec/support/simplecov_helper.rb +9 -5
  115. data/spec/support/simplecov_quality_formatter.rb +10 -6
  116. data/spec/unit/apns_feedback_spec.rb +3 -3
  117. data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
  118. data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
  119. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  120. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  121. data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
  122. data/spec/unit/client/active_record/app_spec.rb +30 -0
  123. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  124. data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
  125. data/spec/unit/client/active_record/notification_spec.rb +15 -0
  126. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  127. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  128. data/spec/unit/configuration_spec.rb +12 -5
  129. data/spec/unit/daemon/adm/delivery_spec.rb +57 -54
  130. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
  131. data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
  132. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +24 -17
  133. data/spec/unit/daemon/app_runner_spec.rb +66 -123
  134. data/spec/unit/daemon/batch_spec.rb +52 -115
  135. data/spec/unit/daemon/delivery_spec.rb +15 -1
  136. data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
  137. data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
  138. data/spec/unit/daemon/dispatcher_loop_spec.rb +7 -12
  139. data/spec/unit/daemon/feeder_spec.rb +40 -39
  140. data/spec/unit/daemon/gcm/delivery_spec.rb +108 -89
  141. data/spec/unit/daemon/reflectable_spec.rb +2 -2
  142. data/spec/unit/daemon/retryable_error_spec.rb +1 -1
  143. data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
  144. data/spec/unit/daemon/signal_handler_spec.rb +72 -0
  145. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +9 -9
  146. data/spec/unit/daemon/store/active_record_spec.rb +38 -47
  147. data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
  148. data/spec/unit/daemon/too_many_requests_error_spec.rb +1 -1
  149. data/spec/unit/daemon/wpns/delivery_spec.rb +61 -50
  150. data/spec/unit/daemon_spec.rb +46 -81
  151. data/spec/unit/embed_spec.rb +4 -2
  152. data/spec/unit/logger_spec.rb +30 -40
  153. data/spec/unit/notification_shared.rb +9 -79
  154. data/spec/unit/push_spec.rb +3 -8
  155. data/spec/unit/reflection_spec.rb +25 -25
  156. data/spec/unit/rpush_spec.rb +1 -2
  157. data/spec/unit_spec_helper.rb +33 -88
  158. metadata +119 -67
  159. data/lib/rpush/TODO +0 -3
  160. data/lib/rpush/adm/app.rb +0 -15
  161. data/lib/rpush/adm/data_validator.rb +0 -11
  162. data/lib/rpush/adm/notification.rb +0 -29
  163. data/lib/rpush/apns/app.rb +0 -29
  164. data/lib/rpush/apns/binary_notification_validator.rb +0 -12
  165. data/lib/rpush/apns/device_token_format_validator.rb +0 -12
  166. data/lib/rpush/apns/feedback.rb +0 -16
  167. data/lib/rpush/apns/notification.rb +0 -84
  168. data/lib/rpush/app.rb +0 -18
  169. data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
  170. data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
  171. data/lib/rpush/gcm/app.rb +0 -11
  172. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
  173. data/lib/rpush/gcm/notification.rb +0 -30
  174. data/lib/rpush/notification.rb +0 -69
  175. data/lib/rpush/notifier.rb +0 -52
  176. data/lib/rpush/payload_data_size_validator.rb +0 -10
  177. data/lib/rpush/railtie.rb +0 -11
  178. data/lib/rpush/registration_ids_count_validator.rb +0 -10
  179. data/lib/rpush/wpns/app.rb +0 -9
  180. data/lib/rpush/wpns/notification.rb +0 -26
  181. data/lib/tasks/cane.rake +0 -18
  182. data/lib/tasks/rpush.rake +0 -16
  183. data/spec/unit/apns/app_spec.rb +0 -29
  184. data/spec/unit/apns/feedback_spec.rb +0 -9
  185. data/spec/unit/apns/notification_spec.rb +0 -208
  186. data/spec/unit/app_spec.rb +0 -30
  187. data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
  188. data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
  189. data/spec/unit/gcm/app_spec.rb +0 -4
  190. data/spec/unit/notification_spec.rb +0 -15
  191. data/spec/unit/notifier_spec.rb +0 -49
  192. data/spec/unit/wpns/app_spec.rb +0 -4
  193. data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -4,13 +4,14 @@ module Rpush
4
4
  extend ServiceConfigMethods
5
5
 
6
6
  HOSTS = {
7
- :production => ['gateway.push.apple.com', 2195],
8
- :development => ['gateway.sandbox.push.apple.com', 2195], # deprecated
9
- :sandbox => ['gateway.sandbox.push.apple.com', 2195]
7
+ production: ['gateway.push.apple.com', 2195],
8
+ development: ['gateway.sandbox.push.apple.com', 2195], # deprecated
9
+ sandbox: ['gateway.sandbox.push.apple.com', 2195]
10
10
  }
11
11
 
12
- dispatcher :tcp, :host => Proc.new { |app| HOSTS[app.environment.to_sym] }
13
- loops Rpush::Daemon::Apns::FeedbackReceiver
12
+ batch_deliveries true
13
+ dispatcher :apns_tcp, host: proc { |app| HOSTS[app.environment.to_sym] }
14
+ loops Rpush::Daemon::Apns::FeedbackReceiver, if: -> { !Rpush.config.push }
14
15
  end
15
16
  end
16
17
  end
@@ -2,60 +2,36 @@ module Rpush
2
2
  module Daemon
3
3
  module Apns
4
4
  class Delivery < Rpush::Daemon::Delivery
5
- SELECT_TIMEOUT = 0.2
6
- ERROR_TUPLE_BYTES = 6
7
- APN_ERRORS = {
8
- 1 => "Processing error",
9
- 2 => "Missing device token",
10
- 3 => "Missing topic",
11
- 4 => "Missing payload",
12
- 5 => "Missing token size",
13
- 6 => "Missing topic size",
14
- 7 => "Missing payload size",
15
- 8 => "Invalid token",
16
- 255 => "None (unknown error)"
17
- }
18
-
19
- def initialize(app, conneciton, notification, batch)
5
+ def initialize(app, connection, batch)
20
6
  @app = app
21
- @connection = conneciton
22
- @notification = notification
7
+ @connection = connection
23
8
  @batch = batch
24
9
  end
25
10
 
26
11
  def perform
27
- begin
28
- @connection.write(@notification.to_binary)
29
- check_for_error if Rpush.config.check_for_errors
30
- mark_delivered
31
- log_info("#{@notification.id} sent to #{@notification.device_token}")
32
- rescue Rpush::DeliveryError, Rpush::Apns::DisconnectionError => error
33
- mark_failed(error.code, error.description)
34
- raise
35
- end
12
+ @connection.write(batch_to_binary)
13
+ mark_batch_delivered
14
+ describe_deliveries
15
+ rescue StandardError => error
16
+ mark_batch_failed(error)
17
+ raise
18
+ ensure
19
+ @batch.all_processed
36
20
  end
37
21
 
38
22
  protected
39
23
 
40
- def check_for_error
41
- if @connection.select(SELECT_TIMEOUT)
42
- error = nil
43
-
44
- if tuple = @connection.read(ERROR_TUPLE_BYTES)
45
- _, code, notification_id = tuple.unpack("ccN")
46
-
47
- description = APN_ERRORS[code.to_i] || "Unknown error. Possible Rpush bug?"
48
- error = Rpush::DeliveryError.new(code, notification_id, description)
49
- else
50
- error = Rpush::Apns::DisconnectionError.new
51
- end
24
+ def batch_to_binary
25
+ payload = ""
26
+ @batch.each_notification do |notification|
27
+ payload << notification.to_binary
28
+ end
29
+ payload
30
+ end
52
31
 
53
- begin
54
- log_error("Error received, reconnecting...")
55
- @connection.reconnect
56
- ensure
57
- raise error if error
58
- end
32
+ def describe_deliveries
33
+ @batch.each_notification do |notification|
34
+ log_info("#{notification.id} sent to #{notification.device_token}")
59
35
  end
60
36
  end
61
37
  end
@@ -7,28 +7,29 @@ module Rpush
7
7
 
8
8
  TUPLE_BYTES = 38
9
9
  HOSTS = {
10
- :production => ['feedback.push.apple.com', 2196],
11
- :development => ['feedback.sandbox.push.apple.com', 2196], # deprecated
12
- :sandbox => ['feedback.sandbox.push.apple.com', 2196]
10
+ production: ['feedback.push.apple.com', 2196],
11
+ development: ['feedback.sandbox.push.apple.com', 2196], # deprecated
12
+ sandbox: ['feedback.sandbox.push.apple.com', 2196]
13
13
  }
14
14
 
15
15
  def initialize(app)
16
16
  @app = app
17
17
  @host, @port = HOSTS[@app.environment.to_sym]
18
- @poll = Rpush.config.feedback_poll
19
18
  @certificate = app.certificate
20
19
  @password = app.password
21
- @interruptible_sleep = InterruptibleSleep.new
20
+ @interruptible_sleep = InterruptibleSleep.new(Rpush.config.feedback_poll)
22
21
  end
23
22
 
24
23
  def start
25
24
  return if Rpush.config.push
25
+ log_info("APNs Feedback Receiver started.")
26
+ @interruptible_sleep.start
26
27
 
27
28
  @thread = Thread.new do
28
29
  loop do
29
30
  break if @stop
30
31
  check_for_feedback
31
- @interruptible_sleep.sleep @poll
32
+ @interruptible_sleep.sleep
32
33
  end
33
34
 
34
35
  Rpush::Daemon.store.release_connection
@@ -37,7 +38,7 @@ module Rpush
37
38
 
38
39
  def stop
39
40
  @stop = true
40
- @interruptible_sleep.interrupt_sleep
41
+ @interruptible_sleep.stop
41
42
  @thread.join if @thread
42
43
  end
43
44
 
@@ -46,10 +47,12 @@ module Rpush
46
47
  begin
47
48
  connection = Rpush::Daemon::TcpConnection.new(@app, @host, @port)
48
49
  connection.connect
50
+ tuple = connection.read(TUPLE_BYTES)
49
51
 
50
- while tuple = connection.read(TUPLE_BYTES)
52
+ while tuple
51
53
  timestamp, device_token = parse_tuple(tuple)
52
54
  create_feedback(timestamp, device_token)
55
+ tuple = connection.read(TUPLE_BYTES)
53
56
  end
54
57
  rescue StandardError => e
55
58
  log_error(e)
@@ -13,20 +13,18 @@ module Rpush
13
13
 
14
14
  def self.enqueue(notifications)
15
15
  notifications.group_by(&:app_id).each do |app_id, group|
16
- batch = Batch.new(group)
17
- if app = runners[app_id]
18
- app.enqueue(batch)
19
- else
20
- Rpush.logger.error("No such app '#{app_id}' for notifications #{batch.describe}.")
21
- end
16
+ sync_app_with_id(app_id) unless runners[app_id]
17
+ runners[app_id].enqueue(group) if runners[app_id]
22
18
  end
19
+ ProcTitle.update
23
20
  end
24
21
 
25
22
  def self.sync
26
- apps = Rpush::App.all
23
+ apps = Rpush::Daemon.store.all_apps
27
24
  apps.each { |app| sync_app(app) }
28
25
  removed = runners.keys - apps.map(&:id)
29
26
  removed.each { |app_id| runners.delete(app_id).stop }
27
+ ProcTitle.update
30
28
  end
31
29
 
32
30
  def self.sync_app(app)
@@ -35,8 +33,8 @@ module Rpush
35
33
  else
36
34
  runner = new(app)
37
35
  begin
38
- runner.start
39
36
  runners[app.id] = runner
37
+ runner.start
40
38
  rescue StandardError => e
41
39
  Rpush.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
42
40
  Rpush.logger.error(e)
@@ -45,25 +43,28 @@ module Rpush
45
43
  end
46
44
  end
47
45
 
46
+ def self.sync_app_with_id(app_id)
47
+ sync_app(Rpush::Daemon.store.app(app_id))
48
+ end
49
+
48
50
  def self.stop
49
51
  runners.values.map(&:stop)
50
52
  runners.clear
51
53
  end
52
54
 
53
- def self.debug
54
- runners.values.map(&:debug)
55
+ def self.num_dispatchers
56
+ runners.values.sum(&:num_dispatcher_loops)
55
57
  end
56
58
 
57
- def self.idle
58
- runners.values.select(&:idle?)
59
+ def self.num_queued
60
+ runners.values.sum(&:queue_size)
59
61
  end
60
62
 
61
- def self.wait
62
- sleep 0.1 while !runners.values.all?(&:idle?)
63
+ def self.debug
64
+ runners.values.map(&:debug)
63
65
  end
64
66
 
65
67
  attr_reader :app
66
- attr_accessor :batch
67
68
 
68
69
  def initialize(app)
69
70
  @app = app
@@ -71,27 +72,40 @@ module Rpush
71
72
  end
72
73
 
73
74
  def start
74
- app.connections.times { dispatchers.push(new_dispatcher_loop) }
75
+ app.connections.times { dispatcher_loops.push(new_dispatcher_loop) }
75
76
  start_loops
76
77
  log_info("Started, #{dispatchers_str}.")
77
78
  end
78
79
 
79
80
  def stop
80
- dispatchers.stop
81
+ wait_until_idle
82
+ stop_dispatcher_loops
81
83
  stop_loops
82
84
  end
83
85
 
84
- def enqueue(batch)
85
- self.batch = batch
86
- batch.notifications.each do |notification|
87
- queue.push([notification, batch])
88
- reflect(:notification_enqueued, notification)
86
+ def wait_until_idle
87
+ sleep 0.5 while queue.size > 0
88
+ end
89
+
90
+ def enqueue(notifications)
91
+ if service.batch_deliveries?
92
+ batch_size = (notifications.size / num_dispatcher_loops).ceil
93
+ notifications.in_groups_of(batch_size, false).each do |batch_notifications|
94
+ batch = Batch.new(batch_notifications)
95
+ queue.push(QueuePayload.new(batch))
96
+ end
97
+ else
98
+ batch = Batch.new(notifications)
99
+ notifications.each do |notification|
100
+ queue.push(QueuePayload.new(batch, notification))
101
+ reflect(:notification_enqueued, notification)
102
+ end
89
103
  end
90
104
  end
91
105
 
92
106
  def sync(app)
93
107
  @app = app
94
- diff = dispatchers.size - app.connections
108
+ diff = dispatcher_loops.size - app.connections
95
109
  return if diff == 0
96
110
  if diff > 0
97
111
  decrement_dispatchers(diff)
@@ -103,53 +117,41 @@ module Rpush
103
117
  end
104
118
 
105
119
  def decrement_dispatchers(num)
106
- num.times { dispatchers.pop }
120
+ num.times { dispatcher_loops.pop }
107
121
  end
108
122
 
109
123
  def increment_dispatchers(num)
110
- num.times { dispatchers.push(new_dispatcher_loop) }
124
+ num.times { dispatcher_loops.push(new_dispatcher_loop) }
111
125
  end
112
126
 
113
127
  def debug
114
- Rpush.logger.info <<-EOS
115
-
116
- #{@app.name}:
117
- dispatchers: #{num_dispatchers}
118
- queued: #{queue_size}
119
- batch size: #{batch_size}
120
- batch processed: #{batch_processed}
121
- idle: #{idle?}
122
- EOS
123
- end
128
+ dispatcher_details = {}
129
+
130
+ dispatcher_loops.loops.each_with_index do |dispatcher_loop, i|
131
+ dispatcher_details[i] = {
132
+ started_at: dispatcher_loop.started_at.iso8601,
133
+ dispatched: dispatcher_loop.dispatch_count,
134
+ thread_status: dispatcher_loop.thread_status
135
+ }
136
+ end
124
137
 
125
- def idle?
126
- batch ? batch.complete? : true
138
+ runner_details = { dispatchers: dispatcher_details, queued: queue_size }
139
+ log_info(JSON.pretty_generate(runner_details))
127
140
  end
128
141
 
129
142
  def queue_size
130
143
  queue.size
131
144
  end
132
145
 
133
- def batch_size
134
- batch ? batch.num_notifications : 0
135
- end
136
-
137
- def batch_processed
138
- batch ? batch.num_processed : 0
139
- end
140
-
141
- def num_dispatchers
142
- dispatchers.size
146
+ def num_dispatcher_loops
147
+ dispatcher_loops.size
143
148
  end
144
149
 
145
- protected
150
+ private
146
151
 
147
152
  def start_loops
148
- service_module.loops.each do |loop_class|
149
- instance = loop_class.new(@app)
150
- instance.start
151
- @loops << instance
152
- end
153
+ @loops = service.loop_instances(@app)
154
+ @loops.map(&:start)
153
155
  end
154
156
 
155
157
  def stop_loops
@@ -157,27 +159,32 @@ module Rpush
157
159
  @loops = []
158
160
  end
159
161
 
162
+ def stop_dispatcher_loops
163
+ dispatcher_loops.stop
164
+ @dispatcher_loops = nil
165
+ end
166
+
160
167
  def new_dispatcher_loop
161
- dispatcher = service_module.new_dispatcher(@app)
168
+ dispatcher = service.new_dispatcher(@app)
162
169
  dispatcher_loop = Rpush::Daemon::DispatcherLoop.new(queue, dispatcher)
163
170
  dispatcher_loop.start
164
171
  dispatcher_loop
165
172
  end
166
173
 
167
- def service_module
168
- return @service_module if defined? @service_module
169
- @service_module = "Rpush::Daemon::#{@app.service_name.camelize}".constantize
174
+ def service
175
+ return @service if defined? @service
176
+ @service = "Rpush::Daemon::#{@app.service_name.camelize}".constantize
170
177
  end
171
178
 
172
179
  def queue
173
180
  @queue ||= Queue.new
174
181
  end
175
182
 
176
- def dispatchers
177
- @dispatchers ||= Rpush::Daemon::DispatcherLoopCollection.new
183
+ def dispatcher_loops
184
+ @dispatcher_loops ||= Rpush::Daemon::DispatcherLoopCollection.new
178
185
  end
179
186
 
180
- def dispatchers_str(count = app.connections)
187
+ def dispatchers_str(count = num_dispatcher_loops)
181
188
  count = count.abs
182
189
  str = count == 1 ? 'dispatcher' : 'dispatchers'
183
190
  "#{count} #{str}"
@@ -3,8 +3,7 @@ module Rpush
3
3
  class Batch
4
4
  include Reflectable
5
5
 
6
- attr_reader :num_processed, :notifications,
7
- :delivered, :failed, :retryable
6
+ attr_reader :num_processed, :notifications, :delivered, :failed, :retryable
8
7
 
9
8
  def initialize(notifications)
10
9
  @notifications = notifications
@@ -15,61 +14,80 @@ module Rpush
15
14
  @mutex = Mutex.new
16
15
  end
17
16
 
18
- def num_notifications
19
- @notifications.size
17
+ def complete?
18
+ @complete == true
19
+ end
20
+
21
+ def each_notification(&blk)
22
+ @notifications.each(&blk)
23
+ end
24
+
25
+ def each_delivered(&blk)
26
+ @delivered.each(&blk)
20
27
  end
21
28
 
22
29
  def mark_retryable(notification, deliver_after)
23
- if Rpush.config.batch_storage_updates
24
- retryable[deliver_after] ||= []
25
- retryable[deliver_after] << notification
26
- Rpush::Daemon.store.mark_retryable(notification, deliver_after, :persist => false)
27
- else
28
- Rpush::Daemon.store.mark_retryable(notification, deliver_after)
29
- reflect(:notification_will_retry, notification)
30
+ @mutex.synchronize do
31
+ @retryable[deliver_after] ||= []
32
+ @retryable[deliver_after] << notification
30
33
  end
34
+ Rpush::Daemon.store.mark_retryable(notification, deliver_after, persist: false)
31
35
  end
32
36
 
33
37
  def mark_delivered(notification)
34
- if Rpush.config.batch_storage_updates
35
- delivered << notification
36
- Rpush::Daemon.store.mark_delivered(notification, Time.now, :persist => false)
37
- else
38
- Rpush::Daemon.store.mark_delivered(notification, Time.now)
39
- reflect(:notification_delivered, notification)
38
+ @mutex.synchronize do
39
+ @delivered << notification
40
+ end
41
+ Rpush::Daemon.store.mark_delivered(notification, Time.now, persist: false)
42
+ end
43
+
44
+ def mark_all_delivered
45
+ @mutex.synchronize do
46
+ @delivered = @notifications
47
+ end
48
+ each_notification do |notification|
49
+ Rpush::Daemon.store.mark_delivered(notification, Time.now, persist: false)
40
50
  end
41
51
  end
42
52
 
43
53
  def mark_failed(notification, code, description)
44
- if Rpush.config.batch_storage_updates
45
- key = [code, description]
46
- failed[key] ||= []
47
- failed[key] << notification
48
- Rpush::Daemon.store.mark_failed(notification, code, description, Time.now, :persist => false)
49
- else
50
- Rpush::Daemon.store.mark_failed(notification, code, description, Time.now)
51
- reflect(:notification_failed, notification)
54
+ key = [code, description]
55
+ @mutex.synchronize do
56
+ @failed[key] ||= []
57
+ @failed[key] << notification
52
58
  end
59
+ Rpush::Daemon.store.mark_failed(notification, code, description, Time.now, persist: false)
53
60
  end
54
61
 
55
- def notification_dispatched
62
+ def mark_all_failed(code, message)
63
+ key = [code, message]
56
64
  @mutex.synchronize do
57
- @num_processed += 1
58
- complete if @num_processed >= @notifications.size
65
+ @failed[key] = @notifications
66
+ end
67
+ each_notification do |notification|
68
+ Rpush::Daemon.store.mark_failed(notification, code, message, Time.now, persist: false)
59
69
  end
60
70
  end
61
71
 
62
- def complete?
63
- @complete == true
72
+ def notification_processed
73
+ @mutex.synchronize do
74
+ @num_processed += 1
75
+ complete if @num_processed >= @notifications.size
76
+ end
64
77
  end
65
78
 
66
- def describe
67
- notifications.map(&:id).join(', ')
79
+ def all_processed
80
+ @mutex.synchronize do
81
+ @num_processed = @notifications.size
82
+ complete
83
+ end
68
84
  end
69
85
 
70
86
  private
71
87
 
72
88
  def complete
89
+ return if complete?
90
+
73
91
  [:complete_delivered, :complete_failed, :complete_retried].each do |method|
74
92
  begin
75
93
  send(method)
@@ -79,36 +97,32 @@ module Rpush
79
97
  end
80
98
  end
81
99
 
82
- notifications.clear
83
100
  @complete = true
84
101
  end
85
102
 
86
103
  def complete_delivered
87
- Rpush::Daemon.store.mark_batch_delivered(delivered)
88
- delivered.each do |notification|
104
+ Rpush::Daemon.store.mark_batch_delivered(@delivered)
105
+ @delivered.each do |notification|
89
106
  reflect(:notification_delivered, notification)
90
107
  end
91
- delivered.clear
92
108
  end
93
109
 
94
110
  def complete_failed
95
- failed.each do |(code, description), notifications|
111
+ @failed.each do |(code, description), notifications|
96
112
  Rpush::Daemon.store.mark_batch_failed(notifications, code, description)
97
113
  notifications.each do |notification|
98
114
  reflect(:notification_failed, notification)
99
115
  end
100
116
  end
101
- failed.clear
102
117
  end
103
118
 
104
119
  def complete_retried
105
- retryable.each do |deliver_after, notifications|
120
+ @retryable.each do |deliver_after, notifications|
106
121
  Rpush::Daemon.store.mark_batch_retryable(notifications, deliver_after)
107
122
  notifications.each do |notification|
108
123
  reflect(:notification_will_retry, notification)
109
124
  end
110
125
  end
111
- retryable.clear
112
126
  end
113
127
  end
114
128
  end