rpush 1.0.0-java → 2.0.0-java

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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +37 -22
  4. data/bin/rpush +13 -4
  5. data/lib/generators/rpush_generator.rb +2 -0
  6. data/lib/generators/templates/add_adm.rb +5 -5
  7. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
  8. data/lib/generators/templates/add_app_to_rapns.rb +2 -2
  9. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
  10. data/lib/generators/templates/add_gcm.rb +32 -32
  11. data/lib/generators/templates/add_rpush.rb +67 -67
  12. data/lib/generators/templates/add_wpns.rb +2 -2
  13. data/lib/generators/templates/create_rapns_apps.rb +5 -5
  14. data/lib/generators/templates/create_rapns_feedback.rb +2 -2
  15. data/lib/generators/templates/create_rapns_notifications.rb +15 -15
  16. data/lib/generators/templates/rpush.rb +28 -7
  17. data/lib/generators/templates/rpush_2_0_0_updates.rb +42 -0
  18. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  19. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  20. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  21. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  22. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  23. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  24. data/lib/rpush/client/active_model/apns/notification.rb +90 -0
  25. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  26. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  27. data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
  28. data/lib/rpush/client/active_model/notification.rb +26 -0
  29. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  30. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  31. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  32. data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
  33. data/lib/rpush/client/active_model.rb +21 -0
  34. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  35. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  36. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  37. data/lib/rpush/client/active_record/apns/feedback.rb +22 -0
  38. data/lib/rpush/client/active_record/apns/notification.rb +46 -0
  39. data/lib/rpush/client/active_record/app.rb +17 -0
  40. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  41. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  42. data/lib/rpush/client/active_record/notification.rb +38 -0
  43. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  44. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  45. data/lib/rpush/client/active_record.rb +19 -0
  46. data/lib/rpush/client/redis/adm/app.rb +14 -0
  47. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  48. data/lib/rpush/client/redis/apns/app.rb +11 -0
  49. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  50. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  51. data/lib/rpush/client/redis/app.rb +24 -0
  52. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  53. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  54. data/lib/rpush/client/redis/notification.rb +68 -0
  55. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  56. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  57. data/lib/rpush/client/redis.rb +35 -0
  58. data/lib/rpush/configuration.rb +27 -6
  59. data/lib/rpush/daemon/adm/delivery.rb +56 -55
  60. data/lib/rpush/daemon/apns/delivery.rb +20 -44
  61. data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
  62. data/lib/rpush/daemon/apns.rb +6 -5
  63. data/lib/rpush/daemon/app_runner.rb +103 -99
  64. data/lib/rpush/daemon/batch.rb +54 -40
  65. data/lib/rpush/daemon/delivery.rb +13 -3
  66. data/lib/rpush/daemon/delivery_error.rb +10 -2
  67. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +114 -0
  68. data/lib/rpush/daemon/dispatcher/http.rb +3 -3
  69. data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
  70. data/lib/rpush/daemon/dispatcher_loop.rb +37 -23
  71. data/lib/rpush/daemon/errors.rb +18 -0
  72. data/lib/rpush/daemon/feeder.rb +28 -39
  73. data/lib/rpush/daemon/gcm/delivery.rb +19 -20
  74. data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
  75. data/lib/rpush/daemon/loggable.rb +2 -4
  76. data/lib/rpush/daemon/proc_title.rb +16 -0
  77. data/lib/rpush/daemon/queue_payload.rb +12 -0
  78. data/lib/rpush/daemon/reflectable.rb +3 -5
  79. data/lib/rpush/daemon/retry_header_parser.rb +6 -6
  80. data/lib/rpush/daemon/retryable_error.rb +2 -0
  81. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  82. data/lib/rpush/daemon/service_config_methods.rb +23 -7
  83. data/lib/rpush/daemon/signal_handler.rb +56 -0
  84. data/lib/rpush/daemon/store/active_record/reconnectable.rb +21 -17
  85. data/lib/rpush/daemon/store/active_record.rb +71 -38
  86. data/lib/rpush/daemon/store/interface.rb +19 -0
  87. data/lib/rpush/daemon/store/redis.rb +149 -0
  88. data/lib/rpush/daemon/string_helpers.rb +15 -0
  89. data/lib/rpush/daemon/synchronizer.rb +60 -0
  90. data/lib/rpush/daemon/tcp_connection.rb +6 -11
  91. data/lib/rpush/daemon/wpns/delivery.rb +21 -30
  92. data/lib/rpush/daemon.rb +40 -60
  93. data/lib/rpush/deprecatable.rb +4 -3
  94. data/lib/rpush/deprecation.rb +7 -10
  95. data/lib/rpush/embed.rb +8 -3
  96. data/lib/rpush/logger.rb +11 -15
  97. data/lib/rpush/push.rb +1 -2
  98. data/lib/rpush/reflection.rb +8 -12
  99. data/lib/rpush/version.rb +1 -1
  100. data/lib/rpush.rb +5 -29
  101. data/lib/tasks/quality.rake +35 -0
  102. data/lib/tasks/test.rake +1 -5
  103. data/spec/.rubocop.yml +4 -0
  104. data/spec/functional/adm_spec.rb +3 -6
  105. data/spec/functional/apns_spec.rb +117 -24
  106. data/spec/functional/embed_spec.rb +20 -20
  107. data/spec/functional/gcm_spec.rb +4 -7
  108. data/spec/functional/new_app_spec.rb +59 -0
  109. data/spec/functional/retry_spec.rb +46 -0
  110. data/spec/functional/synchronization_spec.rb +68 -0
  111. data/spec/functional/wpns_spec.rb +3 -6
  112. data/spec/functional_spec_helper.rb +26 -0
  113. data/spec/integration/rpush_spec.rb +13 -0
  114. data/spec/integration/support/gcm_success_response.json +1 -0
  115. data/spec/spec_helper.rb +60 -0
  116. data/spec/support/active_record_setup.rb +48 -0
  117. data/{config → spec/support/config}/database.yml +0 -0
  118. data/spec/support/install.sh +43 -7
  119. data/spec/support/simplecov_helper.rb +9 -5
  120. data/spec/support/simplecov_quality_formatter.rb +10 -6
  121. data/spec/unit/apns_feedback_spec.rb +3 -3
  122. data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
  123. data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
  124. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  125. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  126. data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
  127. data/spec/unit/client/active_record/app_spec.rb +30 -0
  128. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  129. data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
  130. data/spec/unit/client/active_record/notification_spec.rb +21 -0
  131. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  132. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  133. data/spec/unit/configuration_spec.rb +12 -5
  134. data/spec/unit/daemon/adm/delivery_spec.rb +66 -55
  135. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
  136. data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
  137. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +22 -17
  138. data/spec/unit/daemon/app_runner_spec.rb +78 -186
  139. data/spec/unit/daemon/batch_spec.rb +52 -115
  140. data/spec/unit/daemon/delivery_spec.rb +15 -1
  141. data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
  142. data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
  143. data/spec/unit/daemon/dispatcher_loop_spec.rb +6 -24
  144. data/spec/unit/daemon/feeder_spec.rb +38 -39
  145. data/spec/unit/daemon/gcm/delivery_spec.rb +122 -101
  146. data/spec/unit/daemon/reflectable_spec.rb +2 -2
  147. data/spec/unit/daemon/retryable_error_spec.rb +1 -1
  148. data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
  149. data/spec/unit/daemon/signal_handler_spec.rb +95 -0
  150. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +48 -27
  151. data/spec/unit/daemon/store/active_record_spec.rb +38 -47
  152. data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
  153. data/spec/unit/daemon/wpns/delivery_spec.rb +58 -50
  154. data/spec/unit/daemon_spec.rb +48 -82
  155. data/spec/unit/embed_spec.rb +6 -4
  156. data/spec/unit/logger_spec.rb +35 -43
  157. data/spec/unit/notification_shared.rb +9 -79
  158. data/spec/unit/push_spec.rb +6 -10
  159. data/spec/unit/reflection_spec.rb +25 -25
  160. data/spec/unit/rpush_spec.rb +1 -2
  161. data/spec/unit_spec_helper.rb +33 -88
  162. metadata +126 -76
  163. data/lib/rpush/TODO +0 -3
  164. data/lib/rpush/adm/app.rb +0 -15
  165. data/lib/rpush/adm/data_validator.rb +0 -11
  166. data/lib/rpush/adm/notification.rb +0 -29
  167. data/lib/rpush/apns/app.rb +0 -29
  168. data/lib/rpush/apns/binary_notification_validator.rb +0 -12
  169. data/lib/rpush/apns/device_token_format_validator.rb +0 -12
  170. data/lib/rpush/apns/feedback.rb +0 -16
  171. data/lib/rpush/apns/notification.rb +0 -84
  172. data/lib/rpush/app.rb +0 -18
  173. data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
  174. data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
  175. data/lib/rpush/daemon/dispatcher_loop_collection.rb +0 -33
  176. data/lib/rpush/daemon/too_many_requests_error.rb +0 -20
  177. data/lib/rpush/gcm/app.rb +0 -11
  178. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
  179. data/lib/rpush/gcm/notification.rb +0 -30
  180. data/lib/rpush/notification.rb +0 -69
  181. data/lib/rpush/notifier.rb +0 -52
  182. data/lib/rpush/payload_data_size_validator.rb +0 -10
  183. data/lib/rpush/railtie.rb +0 -11
  184. data/lib/rpush/registration_ids_count_validator.rb +0 -10
  185. data/lib/rpush/wpns/app.rb +0 -9
  186. data/lib/rpush/wpns/notification.rb +0 -26
  187. data/lib/tasks/cane.rake +0 -18
  188. data/lib/tasks/rpush.rake +0 -16
  189. data/spec/unit/apns/app_spec.rb +0 -29
  190. data/spec/unit/apns/feedback_spec.rb +0 -9
  191. data/spec/unit/apns/notification_spec.rb +0 -208
  192. data/spec/unit/app_spec.rb +0 -30
  193. data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
  194. data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +0 -37
  195. data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
  196. data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
  197. data/spec/unit/gcm/app_spec.rb +0 -4
  198. data/spec/unit/notification_spec.rb +0 -15
  199. data/spec/unit/notifier_spec.rb +0 -49
  200. data/spec/unit/wpns/app_spec.rb +0 -4
  201. data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -1,44 +1,51 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Rpush::Daemon::Gcm::Delivery do
4
- let(:app) { Rpush::Gcm::App.new(:name => 'MyApp', :auth_key => 'abc123') }
5
- let(:notification) { Rpush::Gcm::Notification.create!(:app => app, :registration_ids => ['xyz'], :deliver_after => Time.now) }
6
- let(:logger) { double(:error => nil, :info => nil, :warn => nil) }
7
- let(:response) { double(:code => 200, :header => {}) }
8
- let(:http) { double(:shutdown => nil, :request => response)}
4
+ let(:app) { Rpush::Gcm::App.create!(name: 'MyApp', auth_key: 'abc123') }
5
+ let(:notification) { Rpush::Gcm::Notification.create!(app: app, registration_ids: ['xyz'], deliver_after: Time.now) }
6
+ let(:logger) { double(error: nil, info: nil, warn: nil) }
7
+ let(:response) { double(code: 200, header: {}) }
8
+ let(:http) { double(shutdown: nil, request: response) }
9
9
  let(:now) { Time.parse('2012-10-14 00:00:00') }
10
- let(:batch) { double(:mark_failed => nil, :mark_delivered => nil, :mark_retryable => nil) }
10
+ let(:batch) { double(mark_failed: nil, mark_delivered: nil, mark_retryable: nil, notification_processed: nil) }
11
11
  let(:delivery) { Rpush::Daemon::Gcm::Delivery.new(app, http, notification, batch) }
12
- let(:store) { double(:create_gcm_notification => double(:id => 2)) }
12
+ let(:store) { double(create_gcm_notification: double(id: 2)) }
13
13
 
14
14
  def perform
15
15
  delivery.perform
16
16
  end
17
17
 
18
+ def perform_with_rescue
19
+ expect { perform }.to raise_error
20
+ end
21
+
18
22
  before do
19
- delivery.stub(:reflect => nil)
20
- Rpush::Daemon.stub(:store => store)
21
- Time.stub(:now => now)
22
- Rpush.stub(:logger => logger)
23
+ delivery.stub(reflect: nil)
24
+ Rpush::Daemon.stub(store: store)
25
+ Time.stub(now: now)
26
+ Rpush.stub(logger: logger)
23
27
  end
24
28
 
25
29
  shared_examples_for 'a notification with some delivery failures' do
26
30
  let(:new_notification) { Rpush::Gcm::Notification.where('id != ?', notification.id).first }
27
31
 
28
- before { response.stub(:body => JSON.dump(body)) }
32
+ before { response.stub(body: JSON.dump(body)) }
29
33
 
30
34
  it 'marks the original notification as failed' do
31
- delivery.should_receive(:mark_failed).with(nil, error_description)
32
- perform rescue Rpush::DeliveryError
35
+ # error = Rpush::DeliveryError.new(nil, notification.id, error_description)
36
+ delivery.should_receive(:mark_failed) do |error|
37
+ error.to_s.should =~ error_description
38
+ end
39
+ perform_with_rescue
33
40
  end
34
41
 
35
42
  it 'creates a new notification for the unavailable devices' do
36
- notification.update_attributes(:registration_ids => ['id_0', 'id_1', 'id_2'], :data => {'one' => 1}, :collapse_key => 'thing', :delay_while_idle => true)
37
- response.stub(:header => { 'retry-after' => 10 })
43
+ notification.update_attributes(registration_ids: %w(id_0 id_1 id_2), data: { 'one' => 1 }, collapse_key: 'thing', delay_while_idle: true)
44
+ response.stub(header: { 'retry-after' => 10 })
38
45
  attrs = { 'collapse_key' => 'thing', 'delay_while_idle' => true, 'app_id' => app.id }
39
46
  store.should_receive(:create_gcm_notification).with(attrs, notification.data,
40
- ['id_0', 'id_2'], now + 10.seconds, notification.app)
41
- perform rescue Rpush::DeliveryError
47
+ %w(id_0 id_2), now + 10.seconds, notification.app)
48
+ perform_with_rescue
42
49
  end
43
50
 
44
51
  it 'raises a DeliveryError' do
@@ -48,7 +55,7 @@ describe Rpush::Daemon::Gcm::Delivery do
48
55
 
49
56
  describe 'a 200 response' do
50
57
  before do
51
- response.stub(:code => 200)
58
+ response.stub(code: 200)
52
59
  end
53
60
 
54
61
  it 'reflects on any IDs which successfully received the notification' do
@@ -61,11 +68,11 @@ describe Rpush::Daemon::Gcm::Delivery do
61
68
  ]
62
69
  }
63
70
 
64
- response.stub(:body => JSON.dump(body))
65
- notification.stub(:registration_ids => ['1', '2'])
71
+ response.stub(body: JSON.dump(body))
72
+ notification.stub(registration_ids: %w(1 2))
66
73
  delivery.should_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '1')
67
74
  delivery.should_not_receive(:reflect).with(:gcm_delivered_to_recipient, notification, '2')
68
- perform rescue Rpush::DeliveryError
75
+ perform_with_rescue
69
76
  end
70
77
 
71
78
  it 'reflects on any IDs which failed to receive the notification' do
@@ -78,11 +85,11 @@ describe Rpush::Daemon::Gcm::Delivery do
78
85
  ]
79
86
  }
80
87
 
81
- response.stub(:body => JSON.dump(body))
82
- notification.stub(:registration_ids => ['1', '2'])
88
+ response.stub(body: JSON.dump(body))
89
+ notification.stub(registration_ids: %w(1 2))
83
90
  delivery.should_receive(:reflect).with(:gcm_failed_to_recipient, notification, 'Err', '1')
84
91
  delivery.should_not_receive(:reflect).with(:gcm_failed_to_recipient, notification, anything, '2')
85
- perform rescue Rpush::DeliveryError
92
+ perform_with_rescue
86
93
  end
87
94
 
88
95
  it 'reflects on canonical IDs' do
@@ -93,40 +100,43 @@ describe Rpush::Daemon::Gcm::Delivery do
93
100
  'results' => [
94
101
  { 'message_id' => '1:000' },
95
102
  { 'message_id' => '1:000', 'registration_id' => 'canonical123' },
96
- { 'message_id' => '1:000' },
97
- ]}
103
+ { 'message_id' => '1:000' }
104
+ ] }
98
105
 
99
- response.stub(:body => JSON.dump(body))
100
- notification.stub(:registration_ids => ['1', '2', '3'])
106
+ response.stub(body: JSON.dump(body))
107
+ notification.stub(registration_ids: %w(1 2 3))
101
108
  delivery.should_receive(:reflect).with(:gcm_canonical_id, '2', 'canonical123')
102
109
  perform
103
110
  end
104
111
 
105
112
  it 'reflects on invalid IDs' do
106
113
  body = {
107
- 'failure' => 1,
108
- 'success' => 2,
109
- 'canonical_ids' => 0,
110
- 'results' => [
111
- { 'message_id' => '1:000' },
112
- { 'error' => 'NotRegistered' },
113
- { 'message_id' => '1:000' },
114
- ]}
114
+ 'failure' => 1,
115
+ 'success' => 2,
116
+ 'canonical_ids' => 0,
117
+ 'results' => [
118
+ { 'message_id' => '1:000' },
119
+ { 'error' => 'NotRegistered' },
120
+ { 'message_id' => '1:000' }
121
+ ]
122
+ }
115
123
 
116
- response.stub(:body => JSON.dump(body))
117
- notification.stub(:registration_ids => ['1', '2', '3'])
124
+ response.stub(body: JSON.dump(body))
125
+ notification.stub(registration_ids: %w(1 2 3))
118
126
  delivery.should_receive(:reflect).with(:gcm_invalid_registration_id, app, 'NotRegistered', '2')
119
- perform rescue Rpush::DeliveryError
127
+ perform_with_rescue
120
128
  end
121
129
 
122
130
  describe 'when delivered successfully to all devices' do
123
- let(:body) {{
124
- 'failure' => 0,
125
- 'success' => 1,
126
- 'results' => [{ 'message_id' => '1:000'}]
127
- }}
131
+ let(:body) do
132
+ {
133
+ 'failure' => 0,
134
+ 'success' => 1,
135
+ 'results' => [{ 'message_id' => '1:000' }]
136
+ }
137
+ end
128
138
 
129
- before { response.stub(:body => JSON.dump(body)) }
139
+ before { response.stub(body: JSON.dump(body)) }
130
140
 
131
141
  it 'marks the notification as delivered' do
132
142
  delivery.should_receive(:mark_delivered)
@@ -141,20 +151,21 @@ describe Rpush::Daemon::Gcm::Delivery do
141
151
 
142
152
  it 'marks a notification as failed if any ids are invalid' do
143
153
  body = {
144
- 'failure' => 1,
145
- 'success' => 2,
146
- 'canonical_ids' => 0,
147
- 'results' => [
148
- { 'message_id' => '1:000' },
149
- { 'error' => 'NotRegistered' },
150
- { 'message_id' => '1:000' },
151
- ]}
154
+ 'failure' => 1,
155
+ 'success' => 2,
156
+ 'canonical_ids' => 0,
157
+ 'results' => [
158
+ { 'message_id' => '1:000' },
159
+ { 'error' => 'NotRegistered' },
160
+ { 'message_id' => '1:000' }
161
+ ]
162
+ }
152
163
 
153
- response.stub(:body => JSON.dump(body))
164
+ response.stub(body: JSON.dump(body))
154
165
  delivery.should_receive(:mark_failed)
155
166
  delivery.should_not_receive(:mark_retryable)
156
167
  store.should_not_receive(:create_gcm_notification)
157
- perform rescue Rpush::DeliveryError
168
+ perform_with_rescue
158
169
  end
159
170
 
160
171
  it 'marks a notification as failed if any deliveries failed that cannot be retried' do
@@ -164,28 +175,32 @@ describe Rpush::Daemon::Gcm::Delivery do
164
175
  'results' => [
165
176
  { 'message_id' => '1:000' },
166
177
  { 'error' => 'InvalidDataKey' }
167
- ]}
168
- response.stub(:body => JSON.dump(body))
169
- delivery.should_receive(:mark_failed).with(nil, "Failed to deliver to all recipients. Errors: InvalidDataKey.")
170
- perform rescue Rpush::DeliveryError
178
+ ] }
179
+ response.stub(body: JSON.dump(body))
180
+ error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients. Errors: InvalidDataKey.')
181
+ delivery.should_receive(:mark_failed).with(error)
182
+ perform_with_rescue
171
183
  end
172
184
 
173
185
  describe 'all deliveries failed with Unavailable or InternalServerError' do
174
- let(:body) {{
175
- 'failure' => 2,
176
- 'success' => 0,
177
- 'results' => [
178
- { 'error' => 'Unavailable' },
179
- { 'error' => 'Unavailable' }
180
- ]}}
186
+ let(:body) do
187
+ {
188
+ 'failure' => 2,
189
+ 'success' => 0,
190
+ 'results' => [
191
+ { 'error' => 'Unavailable' },
192
+ { 'error' => 'Unavailable' }
193
+ ]
194
+ }
195
+ end
181
196
 
182
197
  before do
183
- response.stub(:body => JSON.dump(body))
184
- notification.stub(:registration_ids => ['1', '2'])
198
+ response.stub(body: JSON.dump(body))
199
+ notification.stub(registration_ids: %w(1 2))
185
200
  end
186
201
 
187
202
  it 'retries the notification respecting the Retry-After header' do
188
- response.stub(:header => { 'retry-after' => 10 })
203
+ response.stub(header: { 'retry-after' => 10 })
189
204
  delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
190
205
  perform
191
206
  end
@@ -209,34 +224,38 @@ describe Rpush::Daemon::Gcm::Delivery do
209
224
  end
210
225
 
211
226
  describe 'all deliveries failed with some as Unavailable or InternalServerError' do
212
- let(:body) {{
213
- 'failure' => 3,
214
- 'success' => 0,
215
- 'results' => [
216
- { 'error' => 'Unavailable' },
217
- { 'error' => 'InvalidDataKey' },
218
- { 'error' => 'Unavailable' }
219
- ]}}
227
+ let(:body) do
228
+ { 'failure' => 3,
229
+ 'success' => 0,
230
+ 'results' => [
231
+ { 'error' => 'Unavailable' },
232
+ { 'error' => 'InvalidDataKey' },
233
+ { 'error' => 'Unavailable' }
234
+ ]
235
+ }
236
+ end
220
237
  let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 1, 2. Errors: Unavailable, InvalidDataKey, Unavailable. 0, 2 will be retried as notification")} [\d]+\./ }
221
238
  it_should_behave_like 'a notification with some delivery failures'
222
239
  end
223
240
 
224
241
  describe 'some deliveries failed with Unavailable or InternalServerError' do
225
- let(:body) {{
226
- 'failure' => 2,
227
- 'success' => 1,
228
- 'results' => [
229
- { 'error' => 'Unavailable' },
230
- { 'message_id' => '1:000' },
231
- { 'error' => 'InternalServerError' }
232
- ]}}
242
+ let(:body) do
243
+ { 'failure' => 2,
244
+ 'success' => 1,
245
+ 'results' => [
246
+ { 'error' => 'Unavailable' },
247
+ { 'message_id' => '1:000' },
248
+ { 'error' => 'InternalServerError' }
249
+ ]
250
+ }
251
+ end
233
252
  let(:error_description) { /#{Regexp.escape("Failed to deliver to recipients 0, 2. Errors: Unavailable, InternalServerError. 0, 2 will be retried as notification")} [\d]+\./ }
234
253
  it_should_behave_like 'a notification with some delivery failures'
235
254
  end
236
255
  end
237
256
 
238
257
  describe 'a 503 response' do
239
- before { response.stub(:code => 503) }
258
+ before { response.stub(code: 503) }
240
259
 
241
260
  it 'logs a warning that the notification will be retried.' do
242
261
  notification.retries = 1
@@ -246,19 +265,19 @@ describe Rpush::Daemon::Gcm::Delivery do
246
265
  end
247
266
 
248
267
  it 'respects an integer Retry-After header' do
249
- response.stub(:header => { 'retry-after' => 10 })
268
+ response.stub(header: { 'retry-after' => 10 })
250
269
  delivery.should_receive(:mark_retryable).with(notification, now + 10.seconds)
251
270
  perform
252
271
  end
253
272
 
254
273
  it 'respects a HTTP-date Retry-After header' do
255
- response.stub(:header => { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
274
+ response.stub(header: { 'retry-after' => 'Wed, 03 Oct 2012 20:55:11 GMT' })
256
275
  delivery.should_receive(:mark_retryable).with(notification, Time.parse('Wed, 03 Oct 2012 20:55:11 GMT'))
257
276
  perform
258
277
  end
259
278
 
260
279
  it 'defaults to exponential back-off if the Retry-After header is not present' do
261
- delivery.should_receive(:mark_retryable).with(notification, now + 2 ** 1)
280
+ delivery.should_receive(:mark_retryable).with(notification, now + 2**1)
262
281
  perform
263
282
  end
264
283
  end
@@ -266,24 +285,24 @@ describe Rpush::Daemon::Gcm::Delivery do
266
285
  describe 'a 500 response' do
267
286
  before do
268
287
  notification.update_attribute(:retries, 2)
269
- response.stub(:code => 500)
288
+ response.stub(code: 500)
270
289
  end
271
290
 
272
291
  it 'logs a warning that the notification has been re-queued.' do
273
292
  notification.retries = 3
274
- notification.deliver_after = now + 2 ** 3
275
- Rpush.logger.should_receive(:warn).with("[MyApp] GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2 ** 3).strftime("%Y-%m-%d %H:%M:%S")} (retry 3).")
293
+ notification.deliver_after = now + 2**3
294
+ Rpush.logger.should_receive(:warn).with("[MyApp] GCM responded with an Internal Error. Notification #{notification.id} will be retried after #{(now + 2**3).strftime("%Y-%m-%d %H:%M:%S")} (retry 3).")
276
295
  perform
277
296
  end
278
297
 
279
298
  it 'retries the notification in accordance with the exponential back-off strategy.' do
280
- delivery.should_receive(:mark_retryable).with(notification, now + 2 ** 3)
299
+ delivery.should_receive(:mark_retryable).with(notification, now + 2**3)
281
300
  perform
282
301
  end
283
302
  end
284
303
 
285
304
  describe 'a 401 response' do
286
- before { response.stub(:code => 401) }
305
+ before { response.stub(code: 401) }
287
306
 
288
307
  it 'raises an error' do
289
308
  expect { perform }.to raise_error(Rpush::DeliveryError)
@@ -291,20 +310,22 @@ describe Rpush::Daemon::Gcm::Delivery do
291
310
  end
292
311
 
293
312
  describe 'a 400 response' do
294
- before { response.stub(:code => 400) }
313
+ before { response.stub(code: 400) }
295
314
 
296
315
  it 'marks the notification as failed' do
297
- delivery.should_receive(:mark_failed).with(400, 'GCM failed to parse the JSON request. Possibly an Rpush bug, please open an issue.')
298
- perform rescue Rpush::DeliveryError
316
+ error = Rpush::DeliveryError.new(400, notification.id, 'GCM failed to parse the JSON request. Possibly an Rpush bug, please open an issue.')
317
+ delivery.should_receive(:mark_failed).with(error)
318
+ perform_with_rescue
299
319
  end
300
320
  end
301
321
 
302
322
  describe 'an un-handled response' do
303
- before { response.stub(:code => 418) }
323
+ before { response.stub(code: 418) }
304
324
 
305
325
  it 'marks the notification as failed' do
306
- delivery.should_receive(:mark_failed).with(418, "I'm a Teapot")
307
- perform rescue Rpush::DeliveryError
326
+ error = Rpush::DeliveryError.new(418, notification.id, "I'm a Teapot")
327
+ delivery.should_receive(:mark_failed).with(error)
328
+ perform_with_rescue
308
329
  end
309
330
  end
310
331
  end
@@ -5,12 +5,12 @@ describe Rpush::Daemon::Reflectable do
5
5
  include Rpush::Daemon::Reflectable
6
6
  end
7
7
 
8
- let(:logger) { double(:error => nil) }
8
+ let(:logger) { double(error: nil) }
9
9
  let(:test_reflectable) { TestReflectable.new }
10
10
 
11
11
  before do
12
12
  Rpush.reflections.stub(:__dispatch)
13
- Rpush.stub(:logger => logger)
13
+ Rpush.stub(logger: logger)
14
14
  end
15
15
 
16
16
  it 'dispatches the given reflection' do
@@ -1,7 +1,7 @@
1
1
  require "unit_spec_helper"
2
2
 
3
3
  describe Rpush::RetryableError do
4
- let(:response) { double(:code => 401, :header => { 'retry-after' => 3600 }) }
4
+ let(:response) { double(code: 401, header: { 'retry-after' => 3600 }) }
5
5
  let(:error) { Rpush::RetryableError.new(401, 12, "Unauthorized", response) }
6
6
 
7
7
  it "returns an informative message" do
@@ -10,10 +10,13 @@ describe Rpush::Daemon::ServiceConfigMethods do
10
10
  ServiceConfigMethodsSpec.delivery_class.should eq ServiceConfigMethodsSpec::Delivery
11
11
  end
12
12
 
13
- it 'gets & sets loops' do
14
- loop_class = double
13
+ it 'instantiates loops' do
14
+ loop_class = Class.new
15
+ app = double
16
+ loop_instance = loop_class.new
17
+ loop_class.should_receive(:new).with(app).and_return(loop_instance)
15
18
  ServiceConfigMethodsSpec.loops loop_class
16
- ServiceConfigMethodsSpec.loops.should eq [loop_class]
19
+ ServiceConfigMethodsSpec.loop_instances(app).should eq [loop_instance]
17
20
  end
18
21
 
19
22
  it 'returns a new dispatcher' do
@@ -0,0 +1,95 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Daemon::SignalHandler do
4
+ def signal_handler(sig)
5
+ Process.kill(sig, Process.pid)
6
+ sleep 0.1
7
+ end
8
+
9
+ def with_handler_start_stop
10
+ Rpush::Daemon::SignalHandler.start
11
+ yield
12
+ ensure
13
+ Rpush::Daemon::SignalHandler.stop
14
+ end
15
+
16
+ describe 'shutdown signals' do
17
+ unless Rpush.jruby? # These tests do not work on JRuby.
18
+ it "shuts down when signaled signaled SIGINT" do
19
+ with_handler_start_stop do
20
+ Rpush::Daemon.should_receive(:shutdown)
21
+ signal_handler('SIGINT')
22
+ end
23
+ end
24
+
25
+ it "shuts down when signaled signaled SIGTERM" do
26
+ with_handler_start_stop do
27
+ Rpush::Daemon.should_receive(:shutdown)
28
+ signal_handler('SIGTERM')
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ describe 'config.embedded = true' do
35
+ before { Rpush.config.embedded = true }
36
+
37
+ it 'does not trap signals' do
38
+ Signal.should_not_receive(:trap)
39
+ Rpush::Daemon::SignalHandler.start
40
+ end
41
+ end
42
+
43
+ describe 'HUP' do
44
+ before do
45
+ Rpush::Daemon::Synchronizer.stub(:sync)
46
+ Rpush::Daemon::Feeder.stub(:wakeup)
47
+ end
48
+
49
+ it 'syncs' do
50
+ with_handler_start_stop do
51
+ Rpush::Daemon::Synchronizer.should_receive(:sync)
52
+ signal_handler('HUP')
53
+ end
54
+ end
55
+
56
+ it 'wakes up the Feeder' do
57
+ with_handler_start_stop do
58
+ Rpush::Daemon::Feeder.should_receive(:wakeup)
59
+ signal_handler('HUP')
60
+ end
61
+ end
62
+ end
63
+
64
+ describe 'USR2' do
65
+ it 'instructs the AppRunner to print debug information' do
66
+ with_handler_start_stop do
67
+ Rpush::Daemon::AppRunner.should_receive(:debug)
68
+ signal_handler('USR2')
69
+ end
70
+ end
71
+ end
72
+
73
+ describe 'error handing' do
74
+ let(:error) { StandardError.new('test') }
75
+
76
+ before { Rpush.stub(logger: double(error: nil)) }
77
+
78
+ it 'logs errors received when handling a signal' do
79
+ Rpush::Daemon::Synchronizer.stub(:sync).and_raise(error)
80
+ expect(Rpush.logger).to receive(:error).with(error)
81
+ with_handler_start_stop do
82
+ signal_handler('HUP')
83
+ end
84
+ end
85
+
86
+ it 'does not interrupt processing of further errors' do
87
+ Rpush::Daemon::Synchronizer.stub(:sync).and_raise(error)
88
+ expect(Rpush::Daemon::AppRunner).to receive(:debug)
89
+ with_handler_start_stop do
90
+ signal_handler('HUP')
91
+ signal_handler('USR2')
92
+ end
93
+ end
94
+ end
95
+ end
@@ -16,13 +16,13 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
16
16
  def perform
17
17
  with_database_reconnect_and_retry do
18
18
  @calls += 1
19
- raise @error if @calls <= @max_calls
19
+ fail @error if @calls <= @max_calls
20
20
  end
21
21
  end
22
22
  end
23
23
 
24
24
  let(:adapter_error_class) do
25
- case $adapter
25
+ case SPEC_ADAPTER
26
26
  when 'postgresql'
27
27
  PGError
28
28
  when 'mysql'
@@ -38,77 +38,98 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
38
38
  when 'sqlite3'
39
39
  SQLite3::Exception
40
40
  else
41
- raise "Please update #{__FILE__} for adapter #{$adapter}"
41
+ fail "Please update #{__FILE__} for adapter #{SPEC_ADAPTER}"
42
42
  end
43
43
  end
44
+
44
45
  let(:error) { adapter_error_class.new("db down!") }
45
- let(:test_double) { TestDouble.new(error, 1) }
46
+ let(:timeout) { ActiveRecord::ConnectionTimeoutError.new("db lazy!") }
47
+ let(:test_doubles) { [TestDouble.new(error, 1), TestDouble.new(timeout, 1)] }
46
48
 
47
49
  before do
48
- @logger = double("Logger", :info => nil, :error => nil, :warn => nil)
50
+ @logger = double("Logger", info: nil, error: nil, warn: nil)
49
51
  Rpush.stub(:logger).and_return(@logger)
50
52
 
51
53
  ActiveRecord::Base.stub(:clear_all_connections!)
52
54
  ActiveRecord::Base.stub(:establish_connection)
53
- test_double.stub(:sleep)
55
+ test_doubles.each { |td| allow(td).to receive(:sleep) }
54
56
  end
55
57
 
56
58
  it "should log the error raised" do
57
59
  Rpush.logger.should_receive(:error).with(error)
58
- test_double.perform
60
+ test_doubles.each(&:perform)
59
61
  end
60
62
 
61
63
  it "should log that the database is being reconnected" do
62
64
  Rpush.logger.should_receive(:warn).with("Lost connection to database, reconnecting...")
63
- test_double.perform
65
+ test_doubles.each(&:perform)
64
66
  end
65
67
 
66
68
  it "should log the reconnection attempt" do
67
69
  Rpush.logger.should_receive(:warn).with("Attempt 1")
68
- test_double.perform
70
+ test_doubles.each(&:perform)
69
71
  end
70
72
 
71
73
  it "should clear all connections" do
72
74
  ActiveRecord::Base.should_receive(:clear_all_connections!)
73
- test_double.perform
75
+ test_doubles.each(&:perform)
74
76
  end
75
77
 
76
78
  it "should establish a new connection" do
77
79
  ActiveRecord::Base.should_receive(:establish_connection)
78
- test_double.perform
80
+ test_doubles.each(&:perform)
79
81
  end
80
82
 
81
83
  it "should test out the new connection by performing a count" do
82
- Rpush::Notification.should_receive(:count)
83
- test_double.perform
84
+ Rpush::Client::ActiveRecord::Notification.should_receive(:count).twice
85
+ test_doubles.each(&:perform)
84
86
  end
85
87
 
86
88
  context "when the reconnection attempt is not successful" do
87
89
  before do
88
- class << Rpush::Notification
90
+ class << Rpush::Client::ActiveRecord::Notification
89
91
  def count
90
92
  @count_calls += 1
91
93
  return if @count_calls == 2
92
- raise @error
94
+ fail @error
93
95
  end
94
96
  end
95
- Rpush::Notification.instance_variable_set("@count_calls", 0)
96
- Rpush::Notification.instance_variable_set("@error", error)
97
+ Rpush::Client::ActiveRecord::Notification.instance_variable_set("@count_calls", 0)
98
+ Rpush::Client::ActiveRecord::Notification.instance_variable_set("@error", error)
97
99
  end
98
100
 
99
- it "should log the 2nd attempt" do
100
- Rpush.logger.should_receive(:warn).with("Attempt 2")
101
- test_double.perform
102
- end
101
+ describe "error behaviour" do
102
+ it "should log the 2nd attempt" do
103
+ Rpush.logger.should_receive(:warn).with("Attempt 2")
104
+ test_doubles[0].perform
105
+ end
103
106
 
104
- it "should log errors raised when the reconnection is not successful" do
105
- Rpush.logger.should_receive(:error).with(error)
106
- test_double.perform
107
+ it "should log errors raised when the reconnection is not successful" do
108
+ Rpush.logger.should_receive(:error).with(error)
109
+ test_doubles[0].perform
110
+ end
111
+
112
+ it "should sleep to avoid thrashing when the database is down" do
113
+ expect(test_doubles[0]).to receive(:sleep).with(2)
114
+ test_doubles[0].perform
115
+ end
107
116
  end
108
117
 
109
- it "should sleep to avoid thrashing when the database is down" do
110
- test_double.should_receive(:sleep).with(2)
111
- test_double.perform
118
+ describe "timeout behaviour" do
119
+ it "should log the 2nd attempt" do
120
+ Rpush.logger.should_receive(:warn).with("Attempt 2")
121
+ test_doubles[1].perform
122
+ end
123
+
124
+ it "should log errors raised when the reconnection is not successful" do
125
+ Rpush.logger.should_receive(:error).with(error)
126
+ test_doubles[1].perform
127
+ end
128
+
129
+ it "should sleep to avoid thrashing when the database is down" do
130
+ expect(test_doubles[1]).to receive(:sleep).with(2)
131
+ test_doubles[1].perform
132
+ end
112
133
  end
113
134
  end
114
135
  end