rpush_extended 3.2.5

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.
Files changed (248) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +365 -0
  3. data/LICENSE +7 -0
  4. data/README.md +393 -0
  5. data/bin/rpush +4 -0
  6. data/lib/generators/rpush_config_generator.rb +7 -0
  7. data/lib/generators/rpush_migration_generator.rb +66 -0
  8. data/lib/generators/templates/add_adm.rb +23 -0
  9. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  10. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  11. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
  12. data/lib/generators/templates/add_gcm.rb +117 -0
  13. data/lib/generators/templates/add_rpush.rb +402 -0
  14. data/lib/generators/templates/add_wpns.rb +16 -0
  15. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  16. data/lib/generators/templates/create_rapns_feedback.rb +25 -0
  17. data/lib/generators/templates/create_rapns_notifications.rb +36 -0
  18. data/lib/generators/templates/rename_rapns_to_rpush.rb +87 -0
  19. data/lib/generators/templates/rpush.rb +135 -0
  20. data/lib/generators/templates/rpush_2_0_0_updates.rb +79 -0
  21. data/lib/generators/templates/rpush_2_1_0_updates.rb +11 -0
  22. data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
  23. data/lib/generators/templates/rpush_2_7_0_updates.rb +12 -0
  24. data/lib/generators/templates/rpush_3_0_0_updates.rb +11 -0
  25. data/lib/generators/templates/rpush_3_0_1_updates.rb +13 -0
  26. data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +9 -0
  27. data/lib/generators/templates/rpush_3_1_1_updates.rb +15 -0
  28. data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +15 -0
  29. data/lib/generators/templates/rpush_3_2_4_updates.rb +9 -0
  30. data/lib/generators/templates/rpush_3_3_0_updates.rb +9 -0
  31. data/lib/generators/templates/rpush_3_3_1_updates.rb +11 -0
  32. data/lib/rpush/apns_feedback.rb +17 -0
  33. data/lib/rpush/cli.rb +213 -0
  34. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  35. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  36. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  37. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  38. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  39. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  40. data/lib/rpush/client/active_model/apns/notification.rb +104 -0
  41. data/lib/rpush/client/active_model/apns2/app.rb +15 -0
  42. data/lib/rpush/client/active_model/apns2/notification.rb +9 -0
  43. data/lib/rpush/client/active_model/apnsp8/app.rb +23 -0
  44. data/lib/rpush/client/active_model/apnsp8/notification.rb +9 -0
  45. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  46. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  47. data/lib/rpush/client/active_model/gcm/notification.rb +59 -0
  48. data/lib/rpush/client/active_model/notification.rb +22 -0
  49. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  50. data/lib/rpush/client/active_model/pushy/app.rb +20 -0
  51. data/lib/rpush/client/active_model/pushy/notification.rb +31 -0
  52. data/lib/rpush/client/active_model/pushy/time_to_live_validator.rb +14 -0
  53. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  54. data/lib/rpush/client/active_model/wns/app.rb +23 -0
  55. data/lib/rpush/client/active_model/wns/notification.rb +32 -0
  56. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  57. data/lib/rpush/client/active_model/wpns/notification.rb +28 -0
  58. data/lib/rpush/client/active_model.rb +34 -0
  59. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  60. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  61. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  62. data/lib/rpush/client/active_record/apns/feedback.rb +18 -0
  63. data/lib/rpush/client/active_record/apns/notification.rb +40 -0
  64. data/lib/rpush/client/active_record/apns2/app.rb +11 -0
  65. data/lib/rpush/client/active_record/apns2/notification.rb +10 -0
  66. data/lib/rpush/client/active_record/apnsp8/app.rb +11 -0
  67. data/lib/rpush/client/active_record/apnsp8/notification.rb +10 -0
  68. data/lib/rpush/client/active_record/app.rb +13 -0
  69. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  70. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  71. data/lib/rpush/client/active_record/notification.rb +42 -0
  72. data/lib/rpush/client/active_record/pushy/app.rb +11 -0
  73. data/lib/rpush/client/active_record/pushy/notification.rb +11 -0
  74. data/lib/rpush/client/active_record/wns/app.rb +11 -0
  75. data/lib/rpush/client/active_record/wns/badge_notification.rb +15 -0
  76. data/lib/rpush/client/active_record/wns/notification.rb +11 -0
  77. data/lib/rpush/client/active_record/wns/raw_notification.rb +13 -0
  78. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  79. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  80. data/lib/rpush/client/active_record.rb +33 -0
  81. data/lib/rpush/client/redis/adm/app.rb +14 -0
  82. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  83. data/lib/rpush/client/redis/apns/app.rb +11 -0
  84. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  85. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  86. data/lib/rpush/client/redis/apns2/app.rb +11 -0
  87. data/lib/rpush/client/redis/apns2/notification.rb +11 -0
  88. data/lib/rpush/client/redis/apnsp8/app.rb +11 -0
  89. data/lib/rpush/client/redis/apnsp8/notification.rb +11 -0
  90. data/lib/rpush/client/redis/app.rb +29 -0
  91. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  92. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  93. data/lib/rpush/client/redis/notification.rb +74 -0
  94. data/lib/rpush/client/redis/pushy/app.rb +16 -0
  95. data/lib/rpush/client/redis/pushy/notification.rb +18 -0
  96. data/lib/rpush/client/redis/wns/app.rb +14 -0
  97. data/lib/rpush/client/redis/wns/badge_notification.rb +15 -0
  98. data/lib/rpush/client/redis/wns/notification.rb +11 -0
  99. data/lib/rpush/client/redis/wns/raw_notification.rb +11 -0
  100. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  101. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  102. data/lib/rpush/client/redis.rb +56 -0
  103. data/lib/rpush/configuration.rb +115 -0
  104. data/lib/rpush/daemon/adm/delivery.rb +226 -0
  105. data/lib/rpush/daemon/adm.rb +9 -0
  106. data/lib/rpush/daemon/apns/delivery.rb +43 -0
  107. data/lib/rpush/daemon/apns/feedback_receiver.rb +90 -0
  108. data/lib/rpush/daemon/apns.rb +17 -0
  109. data/lib/rpush/daemon/apns2/delivery.rb +127 -0
  110. data/lib/rpush/daemon/apns2.rb +10 -0
  111. data/lib/rpush/daemon/apnsp8/delivery.rb +166 -0
  112. data/lib/rpush/daemon/apnsp8/token.rb +43 -0
  113. data/lib/rpush/daemon/apnsp8.rb +10 -0
  114. data/lib/rpush/daemon/app_runner.rb +190 -0
  115. data/lib/rpush/daemon/batch.rb +138 -0
  116. data/lib/rpush/daemon/constants.rb +59 -0
  117. data/lib/rpush/daemon/delivery.rb +46 -0
  118. data/lib/rpush/daemon/delivery_error.rb +27 -0
  119. data/lib/rpush/daemon/dispatcher/apns_http2.rb +51 -0
  120. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +152 -0
  121. data/lib/rpush/daemon/dispatcher/apnsp8_http2.rb +33 -0
  122. data/lib/rpush/daemon/dispatcher/http.rb +21 -0
  123. data/lib/rpush/daemon/dispatcher/tcp.rb +22 -0
  124. data/lib/rpush/daemon/dispatcher_loop.rb +73 -0
  125. data/lib/rpush/daemon/errors.rb +18 -0
  126. data/lib/rpush/daemon/feeder.rb +69 -0
  127. data/lib/rpush/daemon/gcm/delivery.rb +241 -0
  128. data/lib/rpush/daemon/gcm.rb +9 -0
  129. data/lib/rpush/daemon/interruptible_sleep.rb +24 -0
  130. data/lib/rpush/daemon/loggable.rb +33 -0
  131. data/lib/rpush/daemon/proc_title.rb +17 -0
  132. data/lib/rpush/daemon/pushy/delivery.rb +90 -0
  133. data/lib/rpush/daemon/pushy.rb +9 -0
  134. data/lib/rpush/daemon/queue_payload.rb +12 -0
  135. data/lib/rpush/daemon/retry_header_parser.rb +23 -0
  136. data/lib/rpush/daemon/retryable_error.rb +22 -0
  137. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  138. data/lib/rpush/daemon/rpc/client.rb +27 -0
  139. data/lib/rpush/daemon/rpc/server.rb +82 -0
  140. data/lib/rpush/daemon/rpc.rb +9 -0
  141. data/lib/rpush/daemon/service_config_methods.rb +51 -0
  142. data/lib/rpush/daemon/signal_handler.rb +75 -0
  143. data/lib/rpush/daemon/store/active_record/reconnectable.rb +80 -0
  144. data/lib/rpush/daemon/store/active_record.rb +214 -0
  145. data/lib/rpush/daemon/store/interface.rb +20 -0
  146. data/lib/rpush/daemon/store/redis.rb +166 -0
  147. data/lib/rpush/daemon/string_helpers.rb +15 -0
  148. data/lib/rpush/daemon/synchronizer.rb +62 -0
  149. data/lib/rpush/daemon/tcp_connection.rb +190 -0
  150. data/lib/rpush/daemon/wns/badge_request.rb +32 -0
  151. data/lib/rpush/daemon/wns/delivery.rb +178 -0
  152. data/lib/rpush/daemon/wns/post_request.rb +33 -0
  153. data/lib/rpush/daemon/wns/raw_request.rb +22 -0
  154. data/lib/rpush/daemon/wns/toast_request.rb +54 -0
  155. data/lib/rpush/daemon/wns.rb +9 -0
  156. data/lib/rpush/daemon/wpns/delivery.rb +132 -0
  157. data/lib/rpush/daemon/wpns.rb +9 -0
  158. data/lib/rpush/daemon.rb +179 -0
  159. data/lib/rpush/deprecatable.rb +24 -0
  160. data/lib/rpush/deprecation.rb +26 -0
  161. data/lib/rpush/embed.rb +41 -0
  162. data/lib/rpush/logger.rb +92 -0
  163. data/lib/rpush/multi_json_helper.rb +16 -0
  164. data/lib/rpush/plugin.rb +44 -0
  165. data/lib/rpush/push.rb +11 -0
  166. data/lib/rpush/reflectable.rb +13 -0
  167. data/lib/rpush/reflection_collection.rb +44 -0
  168. data/lib/rpush/reflection_public_methods.rb +11 -0
  169. data/lib/rpush/version.rb +14 -0
  170. data/lib/rpush.rb +43 -0
  171. data/lib/tasks/quality.rake +35 -0
  172. data/lib/tasks/test.rake +69 -0
  173. data/spec/.rubocop.yml +4 -0
  174. data/spec/functional/adm_spec.rb +50 -0
  175. data/spec/functional/apns2_spec.rb +232 -0
  176. data/spec/functional/apns_spec.rb +162 -0
  177. data/spec/functional/cli_spec.rb +36 -0
  178. data/spec/functional/embed_spec.rb +49 -0
  179. data/spec/functional/gcm_spec.rb +46 -0
  180. data/spec/functional/new_app_spec.rb +44 -0
  181. data/spec/functional/pushy_spec.rb +22 -0
  182. data/spec/functional/retry_spec.rb +42 -0
  183. data/spec/functional/synchronization_spec.rb +97 -0
  184. data/spec/functional/wpns_spec.rb +71 -0
  185. data/spec/functional_spec_helper.rb +32 -0
  186. data/spec/spec_helper.rb +69 -0
  187. data/spec/support/active_record_setup.rb +73 -0
  188. data/spec/support/cert_with_password.pem +90 -0
  189. data/spec/support/cert_without_password.pem +59 -0
  190. data/spec/support/config/database.yml +44 -0
  191. data/spec/support/simplecov_helper.rb +24 -0
  192. data/spec/support/simplecov_quality_formatter.rb +12 -0
  193. data/spec/tmp/.gitkeep +0 -0
  194. data/spec/unit/apns_feedback_spec.rb +28 -0
  195. data/spec/unit/client/active_record/adm/app_spec.rb +58 -0
  196. data/spec/unit/client/active_record/adm/notification_spec.rb +43 -0
  197. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  198. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  199. data/spec/unit/client/active_record/apns/notification_spec.rb +324 -0
  200. data/spec/unit/client/active_record/app_spec.rb +30 -0
  201. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  202. data/spec/unit/client/active_record/gcm/notification_spec.rb +67 -0
  203. data/spec/unit/client/active_record/notification_spec.rb +21 -0
  204. data/spec/unit/client/active_record/pushy/app_spec.rb +17 -0
  205. data/spec/unit/client/active_record/pushy/notification_spec.rb +65 -0
  206. data/spec/unit/client/active_record/wns/badge_notification_spec.rb +15 -0
  207. data/spec/unit/client/active_record/wns/raw_notification_spec.rb +26 -0
  208. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  209. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  210. data/spec/unit/configuration_spec.rb +46 -0
  211. data/spec/unit/daemon/adm/delivery_spec.rb +253 -0
  212. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  213. data/spec/unit/daemon/apns/delivery_spec.rb +108 -0
  214. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +119 -0
  215. data/spec/unit/daemon/app_runner_spec.rb +188 -0
  216. data/spec/unit/daemon/batch_spec.rb +169 -0
  217. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  218. data/spec/unit/daemon/delivery_spec.rb +51 -0
  219. data/spec/unit/daemon/dispatcher/http_spec.rb +34 -0
  220. data/spec/unit/daemon/dispatcher/tcp_spec.rb +32 -0
  221. data/spec/unit/daemon/dispatcher_loop_spec.rb +53 -0
  222. data/spec/unit/daemon/feeder_spec.rb +96 -0
  223. data/spec/unit/daemon/gcm/delivery_spec.rb +387 -0
  224. data/spec/unit/daemon/proc_title_spec.rb +11 -0
  225. data/spec/unit/daemon/pushy/delivery_spec.rb +159 -0
  226. data/spec/unit/daemon/retryable_error_spec.rb +14 -0
  227. data/spec/unit/daemon/service_config_methods_spec.rb +36 -0
  228. data/spec/unit/daemon/signal_handler_spec.rb +99 -0
  229. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +165 -0
  230. data/spec/unit/daemon/store/active_record_spec.rb +357 -0
  231. data/spec/unit/daemon/store/redis_spec.rb +365 -0
  232. data/spec/unit/daemon/tcp_connection_spec.rb +292 -0
  233. data/spec/unit/daemon/wns/delivery_spec.rb +176 -0
  234. data/spec/unit/daemon/wns/post_request_spec.rb +117 -0
  235. data/spec/unit/daemon/wpns/delivery_spec.rb +167 -0
  236. data/spec/unit/daemon_spec.rb +138 -0
  237. data/spec/unit/deprecatable_spec.rb +32 -0
  238. data/spec/unit/deprecation_spec.rb +15 -0
  239. data/spec/unit/embed_spec.rb +47 -0
  240. data/spec/unit/logger_spec.rb +127 -0
  241. data/spec/unit/notification_shared.rb +53 -0
  242. data/spec/unit/plugin_spec.rb +36 -0
  243. data/spec/unit/push_spec.rb +34 -0
  244. data/spec/unit/reflectable_spec.rb +27 -0
  245. data/spec/unit/reflection_collection_spec.rb +26 -0
  246. data/spec/unit/rpush_spec.rb +8 -0
  247. data/spec/unit_spec_helper.rb +26 -0
  248. metadata +709 -0
@@ -0,0 +1,135 @@
1
+ Rpush.configure do |config|
2
+
3
+ # Supported clients are :active_record and :redis
4
+ config.client = :active_record
5
+
6
+ # Options passed to Redis.new
7
+ # config.redis_options = {}
8
+
9
+ # Frequency in seconds to check for new notifications.
10
+ config.push_poll = 2
11
+
12
+ # The maximum number of notifications to load from the store every `push_poll` seconds.
13
+ # If some notifications are still enqueued internally, Rpush will load the batch_size less
14
+ # the number enqueued. An exception to this is if the service is able to receive multiple
15
+ # notification payloads over the connection with a single write, such as APNs.
16
+ config.batch_size = 100
17
+
18
+ # Path to write PID file. Relative to current directory unless absolute.
19
+ config.pid_file = 'tmp/rpush.pid'
20
+
21
+ # Path to log file. Relative to current directory unless absolute.
22
+ config.log_file = 'log/rpush.log'
23
+
24
+ config.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::INFO
25
+
26
+ # Define a custom logger.
27
+ # config.logger = MyLogger.new
28
+
29
+ # config.apns.feedback_receiver.enabled = true
30
+ # config.apns.feedback_receiver.frequency = 60
31
+
32
+ end
33
+
34
+ Rpush.reflect do |on|
35
+
36
+ # Called with a Rpush::Apns::Feedback instance when feedback is received
37
+ # from the APNs that a notification has failed to be delivered.
38
+ # Further notifications should not be sent to the device.
39
+ # on.apns_feedback do |feedback|
40
+ # end
41
+
42
+ # Called when a notification is queued internally for delivery.
43
+ # The internal queue for each app runner can be inspected:
44
+ #
45
+ # Rpush::Daemon::AppRunner.runners.each do |app_id, runner|
46
+ # runner.app
47
+ # runner.queue_size
48
+ # end
49
+ #
50
+ # on.notification_enqueued do |notification|
51
+ # end
52
+
53
+ # Called when a notification is successfully delivered.
54
+ # on.notification_delivered do |notification|
55
+ # end
56
+
57
+ # Called when notification delivery failed.
58
+ # Call 'error_code' and 'error_description' on the notification for the cause.
59
+ # on.notification_failed do |notification|
60
+ # end
61
+
62
+ # Called when the notification delivery failed and only the notification ID
63
+ # is present in memory.
64
+ # on.notification_id_failed do |app, notification_id, error_code, error_description|
65
+ # end
66
+
67
+ # Called when a notification will be retried at a later date.
68
+ # Call 'deliver_after' on the notification for the next delivery date
69
+ # and 'retries' for the number of times this notification has been retried.
70
+ # on.notification_will_retry do |notification|
71
+ # end
72
+
73
+ # Called when a notification will be retried and only the notification ID
74
+ # is present in memory.
75
+ # on.notification_id_will_retry do |app, notification_id, retry_after|
76
+ # end
77
+
78
+ # Called when a TCP connection is lost and will be reconnected.
79
+ # on.tcp_connection_lost do |app, error|
80
+ # end
81
+
82
+ # Called for each recipient which successfully receives a notification. This
83
+ # can occur more than once for the same notification when there are multiple
84
+ # recipients.
85
+ # on.gcm_delivered_to_recipient do |notification, registration_id|
86
+ # end
87
+
88
+ # Called for each recipient which fails to receive a notification. This
89
+ # can occur more than once for the same notification when there are multiple
90
+ # recipients. (do not handle invalid registration IDs here)
91
+ # on.gcm_failed_to_recipient do |notification, error, registration_id|
92
+ # end
93
+
94
+ # Called when the GCM returns a canonical registration ID.
95
+ # You will need to replace old_id with canonical_id in your records.
96
+ # on.gcm_canonical_id do |old_id, canonical_id|
97
+ # end
98
+
99
+ # Called when the GCM returns a failure that indicates an invalid registration id.
100
+ # You will need to delete the registration_id from your records.
101
+ # on.gcm_invalid_registration_id do |app, error, registration_id|
102
+ # end
103
+
104
+ # Called when an SSL certificate will expire within 1 month.
105
+ # Implement on.error to catch errors raised when the certificate expires.
106
+ # on.ssl_certificate_will_expire do |app, expiration_time|
107
+ # end
108
+
109
+ # Called when an SSL certificate has been revoked.
110
+ # on.ssl_certificate_revoked do |app, error|
111
+ # end
112
+
113
+ # Called when the ADM returns a canonical registration ID.
114
+ # You will need to replace old_id with canonical_id in your records.
115
+ # on.adm_canonical_id do |old_id, canonical_id|
116
+ # end
117
+
118
+ # Called when Failed to deliver to ADM. Check the 'reason' string for further
119
+ # explanations.
120
+ #
121
+ # If the reason is the string 'Unregistered', you should remove
122
+ # this registration id from your records.
123
+ # on.adm_failed_to_recipient do |notification, registration_id, reason|
124
+ # end
125
+
126
+ # Called when Failed to deliver to WNS. Check the 'reason' string for further
127
+ # explanations.
128
+ # You should remove this uri from your records
129
+ # on.wns_invalid_channel do |notification, uri, reason|
130
+ # end
131
+
132
+ # Called when an exception is raised.
133
+ # on.error do |error|
134
+ # end
135
+ end
@@ -0,0 +1,79 @@
1
+ class Rpush200Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ module Rpush
3
+ class App < ActiveRecord::Base
4
+ self.table_name = 'rpush_apps'
5
+ end
6
+
7
+ class Notification < ActiveRecord::Base
8
+ self.table_name = 'rpush_notifications'
9
+ end
10
+ end
11
+
12
+ def self.update_type(model, from, to)
13
+ model.where(type: from).update_all(type: to)
14
+ end
15
+
16
+ def self.up
17
+ add_column :rpush_notifications, :processing, :boolean, null: false, default: false
18
+ add_column :rpush_notifications, :priority, :integer, null: true
19
+
20
+ if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
21
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
22
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
23
+ end
24
+ else
25
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
26
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
27
+ end
28
+ end
29
+
30
+ add_index :rpush_notifications, [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed'
31
+
32
+ rename_column :rpush_feedback, :app, :app_id
33
+
34
+ if postgresql?
35
+ execute('ALTER TABLE rpush_feedback ALTER COLUMN app_id TYPE integer USING (trim(app_id)::integer)')
36
+ else
37
+ change_column :rpush_feedback, :app_id, :integer
38
+ end
39
+
40
+ [:Apns, :Gcm, :Wpns, :Adm].each do |service|
41
+ update_type(Rpush200Updates::Rpush::App, "Rpush::#{service}::App", "Rpush::Client::ActiveRecord::#{service}::App")
42
+ update_type(Rpush200Updates::Rpush::Notification, "Rpush::#{service}::Notification", "Rpush::Client::ActiveRecord::#{service}::Notification")
43
+ end
44
+ end
45
+
46
+ def self.down
47
+ [:Apns, :Gcm, :Wpns, :Adm].each do |service|
48
+ update_type(Rpush200Updates::Rpush::App, "Rpush::Client::ActiveRecord::#{service}::App", "Rpush::#{service}::App")
49
+ update_type(Rpush200Updates::Rpush::Notification, "Rpush::Client::ActiveRecord::#{service}::Notification", "Rpush::#{service}::Notification")
50
+ end
51
+
52
+ change_column :rpush_feedback, :app_id, :string
53
+ rename_column :rpush_feedback, :app_id, :app
54
+
55
+ if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
56
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
57
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
58
+ end
59
+ else
60
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
61
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
62
+ end
63
+ end
64
+
65
+ add_index :rpush_notifications, [:app_id, :delivered, :failed, :deliver_after], name: 'index_rpush_notifications_multi'
66
+
67
+ remove_column :rpush_notifications, :priority
68
+ remove_column :rpush_notifications, :processing
69
+ end
70
+
71
+ def self.adapter_name
72
+ env = (defined?(Rails) && Rails.env) ? Rails.env : 'development'
73
+ Hash[ActiveRecord::Base.configurations[env].map { |k,v| [k.to_sym,v] }][:adapter]
74
+ end
75
+
76
+ def self.postgresql?
77
+ adapter_name =~ /postgresql|postgis/
78
+ end
79
+ end
@@ -0,0 +1,11 @@
1
+ class Rpush210Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :url_args, :text, null: true
4
+ add_column :rpush_notifications, :category, :string, null: true
5
+ end
6
+
7
+ def self.down
8
+ remove_column :rpush_notifications, :url_args
9
+ remove_column :rpush_notifications, :category
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ class Rpush260Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :content_available, :boolean, default: false
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rpush_notifications, :content_available
8
+ end
9
+ end
10
+
@@ -0,0 +1,12 @@
1
+ class Rpush270Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ change_column :rpush_notifications, :alert, :text
4
+ add_column :rpush_notifications, :notification, :text
5
+ end
6
+
7
+ def self.down
8
+ change_column :rpush_notifications, :alert, :string
9
+ remove_column :rpush_notifications, :notification
10
+ end
11
+ end
12
+
@@ -0,0 +1,11 @@
1
+ class Rpush300Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :mutable_content, :boolean, default: false
4
+ change_column :rpush_notifications, :sound, :string, default: nil
5
+ end
6
+
7
+ def self.down
8
+ remove_column :rpush_notifications, :mutable_content
9
+ change_column :rpush_notifications, :sound, :string, default: 'default'
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class Rpush301Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ change_column_null :rpush_notifications, :mutable_content, false
4
+ change_column_null :rpush_notifications, :content_available, false
5
+ change_column_null :rpush_notifications, :alert_is_json, false
6
+ end
7
+
8
+ def self.down
9
+ change_column_null :rpush_notifications, :mutable_content, true
10
+ change_column_null :rpush_notifications, :content_available, true
11
+ change_column_null :rpush_notifications, :alert_is_json, true
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class Rpush310AddPushy < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :external_device_id, :string, null: true
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rpush_notifications, :external_device_id
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ class Rpush311Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ change_table :rpush_notifications do |t|
4
+ t.remove_index name: 'index_rpush_notifications_multi'
5
+ t.index [:delivered, :failed, :processing, :deliver_after, :created_at], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed'
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ change_table :rpush_notifications do |t|
11
+ t.remove_index name: 'index_rpush_notifications_multi'
12
+ t.index [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class Rpush320AddApnsP8 < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_apps, :apn_key, :string, null: true
4
+ add_column :rpush_apps, :apn_key_id, :string, null: true
5
+ add_column :rpush_apps, :team_id, :string, null: true
6
+ add_column :rpush_apps, :bundle_id, :string, null: true
7
+ end
8
+
9
+ def self.down
10
+ remove_column :rpush_apps, :apn_key
11
+ remove_column :rpush_apps, :apn_key_id
12
+ remove_column :rpush_apps, :team_id
13
+ remove_column :rpush_apps, :bundle_id
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ class Rpush324Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ change_column :rpush_apps, :apn_key, :text, null: true
4
+ end
5
+
6
+ def self.down
7
+ change_column :rpush_apps, :apn_key, :string, null: true
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Rpush330Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :thread_id, :string, null: true
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rpush_notifications, :thread_id
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class Rpush331Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ change_column :rpush_notifications, :device_token, :text, null: true
4
+ change_column :rpush_feedback, :device_token, :text, null: true
5
+ end
6
+
7
+ def self.down
8
+ change_column :rpush_notifications, :device_token, :string, { null: true, limit: 64 }
9
+ change_column :rpush_feedback, :device_token, :string, { null: true, limit: 64 }
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module Rpush
2
+ def self.apns_feedback
3
+ require 'rpush/daemon'
4
+ Rpush::Daemon.common_init
5
+
6
+ Rpush::Apns::App.all.each do |app|
7
+ # Redis stores every App type on the same namespace, hence the
8
+ # additional filtering
9
+ next unless app.service_name == 'apns'
10
+
11
+ receiver = Rpush::Daemon::Apns::FeedbackReceiver.new(app)
12
+ receiver.check_for_feedback
13
+ end
14
+
15
+ nil
16
+ end
17
+ end
data/lib/rpush/cli.rb ADDED
@@ -0,0 +1,213 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'thor'
4
+ require 'ansi/code'
5
+
6
+ module Rpush
7
+ class CLI < Thor
8
+ def self.detect_rails?
9
+ ['bin/rails', 'script/rails'].any? { |path| File.exist?(path) }
10
+ end
11
+
12
+ def self.default_config_path
13
+ detect_rails? ? 'config/initializers/rpush.rb' : 'config/rpush.rb'
14
+ end
15
+
16
+ class_option :config, type: :string, aliases: '-c', default: default_config_path
17
+ class_option 'rails-env', type: :string, aliases: '-e', default: 'development'
18
+
19
+ option :foreground, type: :boolean, aliases: '-f', default: false
20
+ option 'pid-file', type: :string, aliases: '-p'
21
+ desc 'start', 'Start Rpush'
22
+ def start
23
+ config_setup
24
+
25
+ require 'rpush/daemon'
26
+ Rpush::Daemon.start
27
+ end
28
+
29
+ desc 'stop', 'Stop Rpush'
30
+ option 'pid-file', type: :string, aliases: '-p'
31
+ def stop
32
+ config_setup
33
+ pid = rpush_process_pid
34
+ return unless pid
35
+
36
+ STDOUT.write "* Stopping Rpush (pid #{pid})... "
37
+ STDOUT.flush
38
+ Process.kill('TERM', pid)
39
+
40
+ loop do
41
+ begin
42
+ Process.getpgid(pid)
43
+ sleep 0.05
44
+ rescue Errno::ESRCH
45
+ break
46
+ end
47
+ end
48
+
49
+ puts ANSI.green { '✔' }
50
+ end
51
+
52
+ desc 'init', 'Initialize Rpush into the current directory'
53
+ option 'active-record', type: :boolean, desc: 'Install ActiveRecord migrations'
54
+ def init
55
+ underscore_option_names
56
+ check_ruby_version
57
+ require 'rails/generators'
58
+
59
+ puts "* " + ANSI.green { 'Installing config...' }
60
+ $RPUSH_CONFIG_PATH = default_config_path # rubocop:disable Style/GlobalVars
61
+ Rails::Generators.invoke('rpush_config')
62
+
63
+ install_migrations = options['active_record']
64
+
65
+ unless options.key?('active_record')
66
+ has_answer = false
67
+ until has_answer
68
+ STDOUT.write "\n* #{ANSI.green { 'Install ActiveRecord migrations?' }} [y/n]: "
69
+ STDOUT.flush
70
+ answer = STDIN.gets.chomp.downcase
71
+ has_answer = %w(y n).include?(answer)
72
+ end
73
+
74
+ install_migrations = answer == 'y'
75
+ end
76
+
77
+ Rails::Generators.invoke('rpush_migration', ['--force']) if install_migrations
78
+
79
+ puts "\n* #{ANSI.green { 'Next steps:' }}"
80
+ puts " - Run 'bundle exec rake db:migrate'." if install_migrations
81
+ puts " - Review and update your configuration in #{default_config_path}."
82
+ puts " - Create your first app, see https://github.com/rpush/rpush for examples."
83
+ puts " - Run 'rpush help' for commands and options."
84
+ end
85
+
86
+ desc 'push', 'Deliver all pending notifications and then exit'
87
+ def push
88
+ config_setup
89
+ Rpush.config.foreground = true
90
+
91
+ Rpush.push
92
+ end
93
+
94
+ desc 'status', 'Show the internal status of the running Rpush instance.'
95
+ def status
96
+ config_setup
97
+
98
+ require 'rpush/daemon'
99
+ rpc = Rpush::Daemon::Rpc::Client.new(rpush_process_pid)
100
+ status = rpc.status
101
+ rpc.close
102
+ puts humanize_json(status)
103
+ end
104
+
105
+ desc 'version', 'Print Rpush version'
106
+ def version
107
+ puts Rpush::VERSION
108
+ end
109
+
110
+ private
111
+
112
+ def config_setup
113
+ underscore_option_names
114
+ check_ruby_version
115
+ configure_rpush
116
+ end
117
+
118
+ def configure_rpush
119
+ load_rails_environment || load_standalone
120
+ end
121
+
122
+ def load_rails_environment
123
+ if detect_rails? && options['rails_env']
124
+ STDOUT.write "* Booting Rails '#{options[:rails_env]}' environment... "
125
+ STDOUT.flush
126
+ ENV['RAILS_ENV'] = options['rails_env']
127
+ load 'config/environment.rb'
128
+ Rpush.config.update(options)
129
+ puts ANSI.green { '✔' }
130
+
131
+ return true
132
+ end
133
+
134
+ false
135
+ end
136
+
137
+ def load_standalone
138
+ if !File.exist?(options[:config])
139
+ STDERR.puts(ANSI.red { 'ERROR: ' } + "#{options[:config]} does not exist. Please run 'rpush init' to generate it or specify the --config option.")
140
+ exit 1
141
+ else
142
+ load options[:config]
143
+ Rpush.config.update(options)
144
+ end
145
+ end
146
+
147
+ def detect_rails?
148
+ self.class.detect_rails?
149
+ end
150
+
151
+ def default_config_path
152
+ self.class.default_config_path
153
+ end
154
+
155
+ def check_ruby_version
156
+ STDERR.puts(ANSI.yellow { 'WARNING: ' } + "You are using an old and unsupported version of Ruby.") if RUBY_VERSION < '2.2.2' && RUBY_ENGINE == 'ruby'
157
+ end
158
+
159
+ def underscore_option_names
160
+ # Underscore option names so that they map directly to Configuration options.
161
+ new_options = options.dup
162
+
163
+ options.each do |k, v|
164
+ new_k = k.to_s.tr('-', '_')
165
+
166
+ if k != new_k
167
+ new_options.delete(k)
168
+ new_options[new_k] = v
169
+ end
170
+ end
171
+
172
+ new_options.freeze
173
+ self.options = new_options
174
+ end
175
+
176
+ def rpush_process_pid
177
+ if Rpush.config.pid_file.blank?
178
+ STDERR.puts(ANSI.red { 'ERROR: ' } + 'config.pid_file is not set.')
179
+ exit 1
180
+ end
181
+
182
+ unless File.exist?(Rpush.config.pid_file)
183
+ STDERR.puts("* Rpush isn't running? #{Rpush.config.pid_file} does not exist.")
184
+ exit 1
185
+ end
186
+
187
+ File.read(Rpush.config.pid_file).strip.to_i
188
+ end
189
+
190
+ def humanize_json(node, str = '', depth = 0) # rubocop:disable Metrics/PerceivedComplexity
191
+ if node.is_a?(Hash)
192
+ node = node.sort_by { |_, v| [Array, Hash].include?(v.class) ? 1 : 0 }
193
+ node.each do |k, v|
194
+ if [Array, Hash].include?(v.class)
195
+ str << "\n#{' ' * depth}#{k}:\n"
196
+ humanize_json(v, str, depth + 1)
197
+ else
198
+ str << "#{' ' * depth}#{k}: #{v}\n"
199
+ end
200
+ end
201
+ elsif node.is_a?(Array)
202
+ node.each do |v|
203
+ str << "\n" if v.is_a?(Hash)
204
+ humanize_json(v, str, depth)
205
+ end
206
+ else
207
+ str << "#{' ' * depth}#{node}\n"
208
+ end
209
+
210
+ str
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,23 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Adm
5
+ module App
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ validates :client_id, :client_secret, presence: true
9
+ end
10
+ end
11
+
12
+ def access_token_expired?
13
+ access_token_expiration.nil? || access_token_expiration < Time.now
14
+ end
15
+
16
+ def service_name
17
+ 'adm'
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Adm
5
+ class DataValidator < ::ActiveModel::Validator
6
+ def validate(record)
7
+ return unless record.collapse_key.nil? && record.data.nil?
8
+ record.errors[:data] << 'must be set unless collapse_key is specified'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Adm
5
+ module Notification
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ validates :registration_ids, presence: true
9
+
10
+ validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 6144
11
+ validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 100
12
+
13
+ validates_with Rpush::Client::ActiveModel::Adm::DataValidator
14
+ end
15
+ end
16
+
17
+ def as_json(options = nil)
18
+ json = { 'data' => data }
19
+ json['consolidationKey'] = collapse_key if collapse_key
20
+ # number of seconds before message is expired
21
+ json['expiresAfter'] = expiry if expiry
22
+ json
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end