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
data/README.md ADDED
@@ -0,0 +1,393 @@
1
+ [![Gem Version](https://badge.fury.io/rb/rpush.svg)](http://badge.fury.io/rb/rpush)
2
+ [![Build Status](https://travis-ci.org/rpush/rpush.svg?branch=master)](https://travis-ci.org/rpush/rpush)
3
+ [![Test Coverage](https://codeclimate.com/github/rpush/rpush/badges/coverage.svg)](https://codeclimate.com/github/rpush/rpush)
4
+ [![Code Climate](https://codeclimate.com/github/rpush/rpush/badges/gpa.svg)](https://codeclimate.com/github/rpush/rpush)
5
+ [![Join the chat at https://gitter.im/rpush/rpush](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/rpush/rpush?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
+
7
+ <img src="https://raw.github.com/rpush/rpush/master/logo.png" align="right" width="200px" />
8
+
9
+ ### Rpush. The push notification service for Ruby.
10
+
11
+ Rpush aims to be the *de facto* gem for sending push notifications in Ruby. Its core goals are ease of use, reliability and a rich feature set. Rpush provides numerous advanced features not found in others gems, giving you greater control & insight as your project grows. These are a few of the reasons why companies worldwide rely on Rpush to deliver their notifications.
12
+
13
+ #### Supported Services
14
+
15
+ * [**Apple Push Notification Service**](#apple-push-notification-service)
16
+ * Including Safari Push Notifications.
17
+ * [**Firebase Cloud Messaging**](#firebase-cloud-messaging) (used to be Google Cloud Messaging)
18
+ * [**Amazon Device Messaging**](#amazon-device-messaging)
19
+ * [**Windows Phone Push Notification Service**](#windows-phone-notification-service)
20
+ * [**Pushy**](#pushy)
21
+
22
+ #### Feature Highlights
23
+
24
+ * Use [**ActiveRecord**](https://github.com/rpush/rpush/wiki/Using-ActiveRecord) or [**Redis**](https://github.com/rpush/rpush/wiki/Using-Redis) for storage. **Note:** Redis support for Rails 5.2 is not yet working if you're using Modis, see [this issue](https://github.com/ileitch/modis/issues/13).
25
+ * Plugins for [**Bugsnag**](https://github.com/rpush/rpush-plugin-bugsnag),
26
+ [**Sentry**](https://github.com/rpush/rpush-plugin-sentry), [**StatsD**](https://github.com/rpush/rpush-plugin-statsd) or [write your own](https://github.com/rpush/rpush/wiki/Writing-a-Plugin).
27
+ * Seamless integration with your projects, including **Rails**.
28
+ * Run as a [daemon](https://github.com/rpush/rpush#as-a-daemon), inside a [job queue](https://github.com/rpush/rpush/wiki/Push-API), on the [command-line](https://github.com/rpush/rpush#on-the-command-line) or [embedded](https://github.com/rpush/rpush/wiki/Embedding-API) in another process.
29
+ * Scales vertically (threading) and horizontally (multiple processes).
30
+ * Designed for uptime - new apps are loaded automatically, signal `HUP` to update running apps.
31
+ * Hooks for fine-grained instrumentation and error handling ([Reflection API](https://github.com/rpush/rpush/wiki/Reflection-API)).
32
+ * Tested with **MRI**
33
+
34
+
35
+ ### Getting Started
36
+
37
+ Add it to your Gemfile:
38
+
39
+ ```ruby
40
+ gem 'rpush'
41
+ ```
42
+
43
+ Initialize Rpush into your project. **Rails will be detected automatically.**
44
+
45
+ ```sh
46
+ $ cd /path/to/project
47
+ $ bundle
48
+ $ bundle exec rpush init
49
+ ```
50
+
51
+ ### Create an App & Notification
52
+
53
+ #### Apple Push Notification Service
54
+
55
+
56
+ If this is your first time using the APNs, you will need to generate SSL certificates. See [Generating Certificates](https://github.com/rpush/rpush/wiki/Generating-Certificates) for instructions.
57
+
58
+ ```ruby
59
+ app = Rpush::Apns::App.new
60
+ app.name = "ios_app"
61
+ app.certificate = File.read("/path/to/sandbox.pem")
62
+ app.environment = "development" # APNs environment.
63
+ app.password = "certificate password"
64
+ app.connections = 1
65
+ app.save!
66
+ ```
67
+
68
+ ```ruby
69
+ n = Rpush::Apns::Notification.new
70
+ n.app = Rpush::Apns::App.find_by_name("ios_app")
71
+ n.device_token = "..." # hex string
72
+ n.alert = "hi mom!"
73
+ n.data = { foo: :bar }
74
+ n.save!
75
+ ```
76
+
77
+ The `url_args` attribute is available for Safari Push Notifications.
78
+
79
+ You should also implement the [ssl_certificate_will_expire](https://github.com/rpush/rpush/wiki/Reflection-API) reflection to monitor when your certificate is due to expire.
80
+
81
+ To use the newer APNs Api replace `Rpush::Apns::App` with `Rpush::Apns2::App`.
82
+
83
+ To use the p8 APNs Api replace `Rpush::Apns::App` with `Rpush::Apnsp8::App`.
84
+
85
+ ```ruby
86
+ app = Rpush::Apnsp8::App.new
87
+ app.name = "ios_app"
88
+ app.apn_key = File.read("/path/to/sandbox.p8")
89
+ app.environment = "development" # APNs environment.
90
+ app.apn_key_id = "APN KEY ID"
91
+ app.team_id = "TEAM ID"
92
+ app.bundle_id = "BUNDLE ID"
93
+ app.connections = 1
94
+ app.save!
95
+ ```
96
+
97
+ ```ruby
98
+ n = Rpush::Apns::Notification.new
99
+ n.app = Rpush::Apnsp8::App.find_by_name("ios_app")
100
+ n.device_token = "..." # hex string
101
+ n.alert = "hi mom!"
102
+ n.data = { foo: :bar }
103
+ n.save!
104
+ ```
105
+ #### Firebase Cloud Messaging
106
+
107
+ FCM and GCM are – as of writing – compatible with each other. See also [this comment](https://github.com/rpush/rpush/issues/284#issuecomment-228330206) for further references.
108
+
109
+ Please refer to the Firebase Console on where to find your `auth_key` (probably called _Server Key_ there). To verify you have the right key, use tools like [Postman](https://www.getpostman.com/), [HTTPie](https://httpie.org/), `curl` or similar before reporting a new issue. See also [this comment](https://github.com/rpush/rpush/issues/346#issuecomment-289218776).
110
+
111
+ ```ruby
112
+ app = Rpush::Gcm::App.new
113
+ app.name = "android_app"
114
+ app.auth_key = "..."
115
+ app.connections = 1
116
+ app.save!
117
+ ```
118
+
119
+ ```ruby
120
+ n = Rpush::Gcm::Notification.new
121
+ n.app = Rpush::Gcm::App.find_by_name("android_app")
122
+ n.registration_ids = ["..."]
123
+ n.data = { message: "hi mom!" }
124
+ n.priority = 'high' # Optional, can be either 'normal' or 'high'
125
+ n.content_available = true # Optional
126
+ # Optional notification payload. See the reference below for more keys you can use!
127
+ n.notification = { body: 'great match!',
128
+ title: 'Portugal vs. Denmark',
129
+ icon: 'myicon'
130
+ }
131
+ n.save!
132
+ ```
133
+
134
+ FCM also requires you to respond to [Canonical IDs](https://github.com/rpush/rpush/wiki/Canonical-IDs).
135
+
136
+ Check the [FCM reference](https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support) for what keys you can use and are available to you. **Note:** Not all are yet implemented in Rpush.
137
+
138
+ #### Amazon Device Messaging
139
+
140
+ ```ruby
141
+ app = Rpush::Adm::App.new
142
+ app.name = "kindle_app"
143
+ app.client_id = "..."
144
+ app.client_secret = "..."
145
+ app.connections = 1
146
+ app.save!
147
+ ```
148
+
149
+ ```ruby
150
+ n = Rpush::Adm::Notification.new
151
+ n.app = Rpush::Adm::App.find_by_name("kindle_app")
152
+ n.registration_ids = ["..."]
153
+ n.data = { message: "hi mom!"}
154
+ n.collapse_key = "Optional consolidationKey"
155
+ n.save!
156
+ ```
157
+
158
+ For more documentation on [ADM](https://developer.amazon.com/sdk/adm.html).
159
+
160
+ #### Windows Phone Notification Service (Windows Phone 8.0 and 7.x)
161
+
162
+ Uses the older [Windows Phone 8 Toast template](https://msdn.microsoft.com/en-us/library/windows/apps/jj662938(v=vs.105).aspx)
163
+
164
+ ```ruby
165
+ app = Rpush::Wpns::App.new
166
+ app.name = "windows_phone_app"
167
+ app.client_id = # Get this from your apps dashboard https://dev.windows.com
168
+ app.client_secret = # Get this from your apps dashboard https://dev.windows.com
169
+ app.connections = 1
170
+ app.save!
171
+ ```
172
+
173
+ ```ruby
174
+ n = Rpush::Wpns::Notification.new
175
+ n.app = Rpush::Wpns::App.find_by_name("windows_phone_app")
176
+ n.uri = "http://..."
177
+ n.data = {title:"MyApp", body:"Hello world", param:"user_param1"}
178
+ n.save!
179
+ ```
180
+
181
+ #### Windows Notification Service (Windows 8.1, 10 Apps & Phone > 8.0)
182
+
183
+ Uses the more recent [Toast template](https://msdn.microsoft.com/en-us/library/windows/apps/xaml/mt631604.aspx)
184
+
185
+ The `client_id` here is the SID URL as seen [here](https://msdn.microsoft.com/en-us/library/windows/apps/hh465407.aspx#7-SIDandSecret). Do not confuse it with the `client_id` on dashboard.
186
+
187
+ You can (optionally) include a launch argument by adding a `launch` key to the notification data.
188
+
189
+ You can (optionally) include an [audio element](https://msdn.microsoft.com/en-us/library/windows/apps/xaml/br230842.aspx) by setting the sound on the notification.
190
+
191
+ ```ruby
192
+ app = Rpush::Wns::App.new
193
+ app.name = "windows_phone_app"
194
+ app.client_id = YOUR_SID_URL
195
+ app.client_secret = YOUR_CLIENT_SECRET
196
+ app.connections = 1
197
+ app.save!
198
+ ```
199
+
200
+ ```ruby
201
+ n = Rpush::Wns::Notification.new
202
+ n.app = Rpush::Wns::App.find_by_name("windows_phone_app")
203
+ n.uri = "http://..."
204
+ n.data = {title:"MyApp", body:"Hello world", launch:"launch-argument"}
205
+ n.sound = "ms-appx:///mynotificationsound.wav"
206
+ n.save!
207
+ ```
208
+
209
+ #### Windows Raw Push Notifications
210
+
211
+ Note: The data is passed as `.to_json` so only this format is supported, altough raw notifications are meant to support any kind of data.
212
+ Current data structure enforces hashes and `.to_json` representation is natural presentation of it.
213
+
214
+ ```ruby
215
+ n = Rpush::Wns::RawNotification.new
216
+ n.app = Rpush::Wns::App.find_by_name("windows_phone_app")
217
+ n.uri = 'http://...'
218
+ n.data = { foo: 'foo', bar: 'bar' }
219
+ n.save!
220
+ ```
221
+
222
+ #### Windows Badge Push Notifications
223
+
224
+ Uses the [badge template](https://msdn.microsoft.com/en-us/library/windows/apps/xaml/br212849.aspx) and the type `wns/badge`.
225
+
226
+ ```ruby
227
+ n = Rpush::Wns::BadgeNotification.new
228
+ n.app = Rpush::Wns::App.find_by_name("windows_phone_app")
229
+ n.uri = 'http://...'
230
+ n.badge = 4
231
+ n.save!
232
+ ```
233
+
234
+ #### Pushy
235
+
236
+ [Pushy](https://pushy.me/) is a highly-reliable push notification gateway, based on [MQTT](https://pushy.me/support#what-is-mqtt) protocol for cross platform push notification delivery that includes web, Android, and iOS. One of its advantages is it allows for reliable notification delivery to Android devices in China where Google Cloud Messaging and Firebase Cloud Messaging are blocked and to custom hardware devices that use Android OS but are not using Google Play Services.
237
+
238
+ Note: current implementation of Pushy only supports Android devices and does not include [subscriptions](https://pushy.me/docs/android/subscribe-topics).
239
+
240
+ ```ruby
241
+ app = Rpush::Pushy::App.new
242
+ app.name = "android_app"
243
+ app.api_key = YOUR_API_KEY
244
+ app.connections = 1
245
+ app.save!
246
+ ```
247
+
248
+ ```ruby
249
+ n = Rpush::Pushy::Notification.new
250
+ n.app = Rpush::Pushy::App.find_by_name("android_app")
251
+ n.registration_ids = ["..."]
252
+ n.data = { message: "hi mom!"}
253
+ n.time_to_live = 60 # seconds
254
+ n.save!
255
+ ```
256
+
257
+ For more documentation on [Pushy](https://pushy.me/docs).
258
+
259
+ ### Running Rpush
260
+
261
+ It is recommended to run Rpush as a separate process in most cases, though embedding and manual modes are provided for low-workload environments.
262
+
263
+ See `rpush help` for all available commands and options.
264
+
265
+ #### As a daemon
266
+
267
+ ```sh
268
+ $ cd /path/to/project
269
+ $ rpush start
270
+ ```
271
+
272
+ #### On the command-line
273
+
274
+ ```sh
275
+ $ rpush push
276
+ ```
277
+
278
+ Rpush will deliver all pending notifications and then exit.
279
+
280
+ #### In a scheduled job
281
+
282
+ ```ruby
283
+ Rpush.push
284
+ Rpush.apns_feedback
285
+ ```
286
+
287
+ See [Push API](https://github.com/rpush/rpush/wiki/Push-API) for more details.
288
+
289
+ #### Embedded inside an existing process
290
+
291
+ ```ruby
292
+ if defined?(Rails)
293
+ ActiveSupport.on_load(:after_initialize) do
294
+ Rpush.embed
295
+ end
296
+ else
297
+ Rpush.embed
298
+ end
299
+ ```
300
+
301
+ Call this during startup of your application, for example, by adding it to the end of `config/rpush.rb`. See [Embedding API](https://github.com/rpush/rpush/wiki/Embedding-API) for more details.
302
+
303
+ #### Using mina
304
+
305
+ If you're using [mina](https://github.com/mina-deploy/mina), there is a gem called [mina-rpush](https://github.com/d4rky-pl/mina-rpush) which helps you control rpush.
306
+
307
+ ### Cleanup
308
+
309
+ Rpush leaves delivered notifications in the database. If you do not clear them out, they will take up more and more space. This isn't great for any database, but is especially problematic if using Redis as the Rpush store. [Here](https://github.com/rpush/rpush/wiki/Using-Redis) is an example solution for cleaning up delivered notifications in Redis.
310
+
311
+ ### Configuration
312
+
313
+ See [Configuration](https://github.com/rpush/rpush/wiki/Configuration) for a list of options.
314
+
315
+ ### Updating Rpush
316
+
317
+ You should run `rpush init` after upgrading Rpush to check for configuration and migration changes.
318
+
319
+ ### From The Wiki
320
+
321
+ ### General
322
+ * [Using Redis](https://github.com/rpush/rpush/wiki/Using-Redis)
323
+ * [Using ActiveRecord](https://github.com/rpush/rpush/wiki/Using-ActiveRecord)
324
+ * [Configuration](https://github.com/rpush/rpush/wiki/Configuration)
325
+ * [Moving from Rapns](https://github.com/rpush/rpush/wiki/Moving-from-Rapns-to-Rpush)
326
+ * [Deploying to Heroku](https://github.com/rpush/rpush/wiki/Heroku)
327
+ * [Hot App Updates](https://github.com/rpush/rpush/wiki/Hot-App-Updates)
328
+ * [Signals](https://github.com/rpush/rpush/wiki/Signals)
329
+ * [Reflection API](https://github.com/rpush/rpush/wiki/Reflection-API)
330
+ * [Push API](https://github.com/rpush/rpush/wiki/Push-API)
331
+ * [Embedding API](https://github.com/rpush/rpush/wiki/Embedding-API)
332
+ * [Writing a Plugin](https://github.com/rpush/rpush/wiki/Writing-a-Plugin)
333
+ * [Implementing your own storage backend](https://github.com/rpush/rpush/wiki/Implementing-your-own-storage-backend)
334
+ * [Upgrading from 2.x to 3.0](https://github.com/rpush/rpush/wiki/Upgrading-from-version-2.x-to-3.0)
335
+
336
+ ### Apple Push Notification Service
337
+ * [Generating Certificates](https://github.com/rpush/rpush/wiki/Generating-Certificates)
338
+ * [Advanced APNs Features](https://github.com/rpush/rpush/wiki/Advanced-APNs-Features)
339
+ * [APNs Delivery Failure Handling](https://github.com/rpush/rpush/wiki/APNs-Delivery-Failure-Handling)
340
+ * [Why open multiple connections to the APNs?](https://github.com/rpush/rpush/wiki/Why-open-multiple-connections-to-the-APNs%3F)
341
+ * [Silent failures might be dropped connections](https://github.com/rpush/rpush/wiki/Dropped-connections)
342
+
343
+ ### Firebase Cloud Messaging
344
+ * [Notification Options](https://github.com/rpush/rpush/wiki/GCM-Notification-Options)
345
+ * [Canonical IDs](https://github.com/rpush/rpush/wiki/Canonical-IDs)
346
+ * [Delivery Failures & Retries](https://github.com/rpush/rpush/wiki/Delivery-Failures-&-Retries)
347
+
348
+ ### Contributing
349
+
350
+ #### Running Tests
351
+
352
+ Rpush uses [Appraisal](https://github.com/thoughtbot/appraisal) to run tests against multiple versions of Ruby on Rails. This helps making sure that Rpush performs correctly with multiple Rails versions.
353
+
354
+ Rpush also uses RSpec for its tests.
355
+
356
+ ##### Bootstrapping your test suite:
357
+
358
+ First, we need to setup a test database, `rpush_test`.
359
+
360
+ E.g. (postgres): `psql -c 'create database rpush_test;' -U postgres >/dev/null`
361
+
362
+ ```
363
+ bundle install
364
+ bundle exec appraisal install
365
+ ```
366
+ This will install all the required gems that requires to test against each version of Rails, which defined in `gemfiles/*.gemfile`.
367
+
368
+ ##### To run a full test suite:
369
+
370
+ ```
371
+ bundle exec appraisal rake
372
+ ```
373
+ This will run RSpec against all versions of Rails.
374
+
375
+ ##### To run a single test
376
+
377
+ You need to specify a `BUNDLE_GEMFILE` pointing to the gemfile before running the normal test command:
378
+
379
+ ```
380
+ BUNDLE_GEMFILE=gemfiles/rails_5.2.gemfile rspec spec/unit/apns_feedback_spec.rb
381
+ ```
382
+
383
+ ##### Multiple database adapter support
384
+
385
+ When running specs, please note that the ActiveRecord adapter can be changed by setting the `ADAPTER` environment variable. For example: `ADAPTER=postgresql rake`.
386
+
387
+ Available adapters for testing are `postgresql`, `jdbcpostgresql`, `mysql2`, `jdbcmysql`, `jdbch2`, and `sqlite3`.
388
+
389
+ Note that the database username is changed at runtime to be the currently logged in user's name. So if you're testing
390
+ with mysql and you're using a user named 'bob', you will need to grant a mysql user 'bob' access to the 'rpush_test'
391
+ mysql database.
392
+
393
+ To switch between ActiveRecord and Redis, set the `CLIENT` environment variable to either `active_record` or `redis`.
data/bin/rpush ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rpush'
4
+ Rpush::CLI.start(ARGV)
@@ -0,0 +1,7 @@
1
+ class RpushConfigGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def copy_config
5
+ copy_file 'rpush.rb', $RPUSH_CONFIG_PATH
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ class RpushMigrationGenerator < Rails::Generators::Base
2
+ include Rails::Generators::Migration
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ class << self
6
+ attr_accessor :next_template
7
+
8
+ def next_migration_number(path)
9
+ return new_migration_number unless next_template
10
+
11
+ if existing_migration = migration_exists?(File.expand_path('db/migrate'), next_template)
12
+ return File.basename(existing_migration).scan(/(\d+)_/).flatten.first
13
+ end
14
+
15
+ new_migration_number
16
+ end
17
+
18
+ def new_migration_number
19
+ @time ||= Time.now.utc
20
+ @calls ||= -1
21
+ @calls += 1
22
+ (@time + @calls.seconds).strftime('%Y%m%d%H%M%S')
23
+ end
24
+ end
25
+
26
+ def copy_migration
27
+ if has_migration?('create_rapns_notifications')
28
+ add_rpush_migration('create_rapns_feedback')
29
+ add_rpush_migration('add_alert_is_json_to_rapns_notifications')
30
+ add_rpush_migration('add_app_to_rapns')
31
+ add_rpush_migration('create_rapns_apps')
32
+ add_rpush_migration('add_gcm')
33
+ add_rpush_migration('add_wpns')
34
+ add_rpush_migration('add_adm')
35
+ add_rpush_migration('rename_rapns_to_rpush')
36
+ add_rpush_migration('add_fail_after_to_rpush_notifications')
37
+ else
38
+ add_rpush_migration('add_rpush')
39
+ end
40
+
41
+ add_rpush_migration('rpush_2_0_0_updates')
42
+ add_rpush_migration('rpush_2_1_0_updates')
43
+ add_rpush_migration('rpush_2_6_0_updates')
44
+ add_rpush_migration('rpush_2_7_0_updates')
45
+ add_rpush_migration('rpush_3_0_0_updates')
46
+ add_rpush_migration('rpush_3_0_1_updates')
47
+ add_rpush_migration('rpush_3_1_0_add_pushy')
48
+ add_rpush_migration('rpush_3_1_1_updates')
49
+ add_rpush_migration('rpush_3_2_0_add_apns_p8')
50
+ add_rpush_migration('rpush_3_2_4_updates')
51
+ add_rpush_migration('rpush_3_3_0_updates')
52
+ add_rpush_migration('rpush_3_3_1_updates')
53
+ end
54
+
55
+ protected
56
+
57
+ def has_migration?(template)
58
+ migration_dir = File.expand_path('db/migrate')
59
+ self.class.migration_exists?(migration_dir, template)
60
+ end
61
+
62
+ def add_rpush_migration(template)
63
+ self.class.next_template = template
64
+ migration_template "#{template}.rb", "db/migrate/#{template}.rb"
65
+ end
66
+ end
@@ -0,0 +1,23 @@
1
+ class AddAdm < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ module Rapns
3
+ class Notification < ActiveRecord::Base
4
+ self.table_name = 'rapns_notifications'
5
+ end
6
+ end
7
+
8
+ def self.up
9
+ add_column :rapns_apps, :client_id, :string, null: true
10
+ add_column :rapns_apps, :client_secret, :string, null: true
11
+ add_column :rapns_apps, :access_token, :string, null: true
12
+ add_column :rapns_apps, :access_token_expiration, :datetime, null: true
13
+ end
14
+
15
+ def self.down
16
+ AddAdm::Rapns::Notification.where(type: 'Rapns::Adm::Notification').delete_all
17
+
18
+ remove_column :rapns_apps, :client_id
19
+ remove_column :rapns_apps, :client_secret
20
+ remove_column :rapns_apps, :access_token
21
+ remove_column :rapns_apps, :access_token_expiration
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ class AddAlertIsJsonToRapnsNotifications < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rapns_notifications, :alert_is_json, :boolean, null: true, default: false
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rapns_notifications, :alert_is_json
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class AddAppToRapns < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rapns_notifications, :app, :string, null: true
4
+ add_column :rapns_feedback, :app, :string, null: true
5
+ end
6
+
7
+ def self.down
8
+ remove_column :rapns_notifications, :app
9
+ remove_column :rapns_feedback, :app
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class AddFailAfterToRpushNotifications < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_notifications, :fail_after, :timestamp, null: true
4
+ end
5
+
6
+ def self.down
7
+ remove_column :rpush_notifications, :fail_after
8
+ end
9
+ end
@@ -0,0 +1,117 @@
1
+ class AddGcm < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ module Rapns
3
+ class App < ActiveRecord::Base
4
+ self.table_name = 'rapns_apps'
5
+ end
6
+
7
+ class Notification < ActiveRecord::Base
8
+ belongs_to :app
9
+ self.table_name = 'rapns_notifications'
10
+ end
11
+ end
12
+
13
+ def self.up
14
+ add_column :rapns_notifications, :type, :string, null: true
15
+ add_column :rapns_apps, :type, :string, null: true
16
+
17
+ AddGcm::Rapns::Notification.update_all type: 'Rapns::Apns::Notification'
18
+ AddGcm::Rapns::App.update_all type: 'Rapns::Apns::App'
19
+
20
+ change_column :rapns_notifications, :type, :string, null: false
21
+ change_column :rapns_apps, :type, :string, null: false
22
+ change_column :rapns_notifications, :device_token, :string, { null: true, limit: 64 }
23
+ change_column :rapns_notifications, :expiry, :integer, { null: true, default: 1.day.to_i }
24
+ change_column :rapns_apps, :environment, :string, null: true
25
+ change_column :rapns_apps, :certificate, :text, null: true, default: nil
26
+
27
+ change_column :rapns_notifications, :error_description, :text, null: true, default: nil
28
+ change_column :rapns_notifications, :sound, :string, default: 'default'
29
+
30
+ rename_column :rapns_notifications, :attributes_for_device, :data
31
+ rename_column :rapns_apps, :key, :name
32
+
33
+ add_column :rapns_apps, :auth_key, :string, null: true
34
+
35
+ add_column :rapns_notifications, :collapse_key, :string, null: true
36
+ add_column :rapns_notifications, :delay_while_idle, :boolean, null: false, default: false
37
+
38
+ reg_ids_type = ActiveRecord::Base.connection.adapter_name.include?('Mysql') ? :mediumtext : :text
39
+ add_column :rapns_notifications, :registration_ids, reg_ids_type, null: true
40
+ add_column :rapns_notifications, :app_id, :integer, null: true
41
+ add_column :rapns_notifications, :retries, :integer, null: true, default: 0
42
+
43
+ AddGcm::Rapns::Notification.reset_column_information
44
+ AddGcm::Rapns::App.reset_column_information
45
+
46
+ AddGcm::Rapns::App.all.each do |app|
47
+ AddGcm::Rapns::Notification.update_all(['app_id = ?', app.id], ['app = ?', app.name])
48
+ end
49
+
50
+ change_column :rapns_notifications, :app_id, :integer, null: false
51
+ remove_column :rapns_notifications, :app
52
+
53
+ if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
54
+ if index_name_exists?(:rapns_notifications, "index_rapns_notifications_multi")
55
+ remove_index :rapns_notifications, name: "index_rapns_notifications_multi"
56
+ elsif index_name_exists?(:rapns_notifications, "index_rapns_notifications_on_delivered_failed_deliver_after")
57
+ remove_index :rapns_notifications, name: "index_rapns_notifications_on_delivered_failed_deliver_after"
58
+ end
59
+ else
60
+ if index_name_exists?(:rapns_notifications, "index_rapns_notifications_multi", true)
61
+ remove_index :rapns_notifications, name: "index_rapns_notifications_multi"
62
+ elsif index_name_exists?(:rapns_notifications, "index_rapns_notifications_on_delivered_failed_deliver_after", false)
63
+ remove_index :rapns_notifications, name: "index_rapns_notifications_on_delivered_failed_deliver_after"
64
+ end
65
+ end
66
+
67
+ add_index :rapns_notifications, [:app_id, :delivered, :failed, :deliver_after], name: "index_rapns_notifications_multi"
68
+ end
69
+
70
+ def self.down
71
+ AddGcm::Rapns::Notification.where(type: 'Rapns::Gcm::Notification').delete_all
72
+
73
+ remove_column :rapns_notifications, :type
74
+ remove_column :rapns_apps, :type
75
+
76
+ change_column :rapns_notifications, :device_token, :string, { null: false, limit: 64 }
77
+ change_column :rapns_notifications, :expiry, :integer, { null: false, default: 1.day.to_i }
78
+ change_column :rapns_apps, :environment, :string, null: false
79
+ change_column :rapns_apps, :certificate, :text, null: false
80
+
81
+ change_column :rapns_notifications, :error_description, :string, null: true, default: nil
82
+ change_column :rapns_notifications, :sound, :string, default: '1.aiff'
83
+
84
+ rename_column :rapns_notifications, :data, :attributes_for_device
85
+ rename_column :rapns_apps, :name, :key
86
+
87
+ remove_column :rapns_apps, :auth_key
88
+
89
+ remove_column :rapns_notifications, :collapse_key
90
+ remove_column :rapns_notifications, :delay_while_idle
91
+ remove_column :rapns_notifications, :registration_ids
92
+ remove_column :rapns_notifications, :retries
93
+
94
+ add_column :rapns_notifications, :app, :string, null: true
95
+
96
+ AddGcm::Rapns::Notification.reset_column_information
97
+ AddGcm::Rapns::App.reset_column_information
98
+
99
+ AddGcm::Rapns::App.all.each do |app|
100
+ AddGcm::Rapns::Notification.update_all(['app = ?', app.key], ['app_id = ?', app.id])
101
+ end
102
+
103
+ if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
104
+ if index_name_exists?(:rapns_notifications, :index_rapns_notifications_multi)
105
+ remove_index :rapns_notifications, name: :index_rapns_notifications_multi
106
+ end
107
+ else
108
+ if index_name_exists?(:rapns_notifications, :index_rapns_notifications_multi, true)
109
+ remove_index :rapns_notifications, name: :index_rapns_notifications_multi
110
+ end
111
+ end
112
+
113
+ remove_column :rapns_notifications, :app_id
114
+
115
+ add_index :rapns_notifications, [:delivered, :failed, :deliver_after], name: :index_rapns_notifications_multi
116
+ end
117
+ end