rpush 1.0.0-java → 2.0.0-java

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