rpush_extended 3.2.5

Sign up to get free protection for your applications and to get access to all the features.
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