rapns 3.2.0-java → 3.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/README.md +9 -18
  3. data/lib/generators/templates/rapns.rb +5 -0
  4. data/lib/rapns.rb +4 -0
  5. data/lib/rapns/apns_feedback.rb +1 -0
  6. data/lib/rapns/configuration.rb +4 -3
  7. data/lib/rapns/daemon.rb +20 -4
  8. data/lib/rapns/daemon/apns/feedback_receiver.rb +9 -11
  9. data/lib/rapns/daemon/delivery.rb +3 -20
  10. data/lib/rapns/daemon/delivery_queue.rb +2 -2
  11. data/lib/rapns/daemon/feeder.rb +5 -10
  12. data/lib/rapns/daemon/gcm/delivery.rb +19 -9
  13. data/lib/rapns/daemon/store/active_record.rb +74 -0
  14. data/lib/rapns/daemon/store/active_record/reconnectable.rb +61 -0
  15. data/lib/rapns/gcm/notification.rb +5 -4
  16. data/lib/rapns/gcm/registration_ids_count_validator.rb +1 -1
  17. data/lib/rapns/logger.rb +6 -2
  18. data/lib/rapns/push.rb +1 -0
  19. data/lib/rapns/reflection.rb +1 -1
  20. data/lib/rapns/version.rb +1 -1
  21. data/spec/unit/apns/notification_spec.rb +2 -0
  22. data/spec/unit/apns_feedback_spec.rb +5 -0
  23. data/spec/unit/configuration_spec.rb +1 -1
  24. data/spec/unit/daemon/apns/delivery_spec.rb +7 -64
  25. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +2 -2
  26. data/spec/unit/daemon/feeder_spec.rb +6 -58
  27. data/spec/unit/daemon/gcm/delivery_spec.rb +49 -57
  28. data/spec/unit/daemon/{database_reconnectable_spec.rb → store/active_record/reconnectable_spec.rb} +4 -3
  29. data/spec/unit/daemon/store/active_record_spec.rb +181 -0
  30. data/spec/unit/daemon_spec.rb +27 -7
  31. data/spec/unit/gcm/notification_spec.rb +2 -9
  32. data/spec/unit/push_spec.rb +5 -0
  33. data/spec/unit/reflection_spec.rb +0 -4
  34. data/spec/unit_spec_helper.rb +4 -1
  35. metadata +28 -25
  36. data/lib/rapns/daemon/database_reconnectable.rb +0 -57
@@ -1,8 +1,9 @@
1
- require "unit_spec_helper"
1
+ require 'unit_spec_helper'
2
+ require 'rapns/daemon/store/active_record/reconnectable'
2
3
 
3
- describe Rapns::Daemon::DatabaseReconnectable do
4
+ describe Rapns::Daemon::Store::ActiveRecord::Reconnectable do
4
5
  class TestDouble
5
- include Rapns::Daemon::DatabaseReconnectable
6
+ include Rapns::Daemon::Store::ActiveRecord::Reconnectable
6
7
 
7
8
  attr_reader :name
8
9
 
@@ -0,0 +1,181 @@
1
+ require 'unit_spec_helper'
2
+ require 'rapns/daemon/store/active_record'
3
+
4
+ describe Rapns::Daemon::Store::ActiveRecord do
5
+ let(:app) { Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
6
+ let(:notification) { Rapns::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
7
+ let(:store) { Rapns::Daemon::Store::ActiveRecord.new }
8
+ let(:now) { Time.now }
9
+
10
+ before { Time.stub(:now => now) }
11
+
12
+ describe 'deliverable_notifications' do
13
+ it 'checks for new notifications with the ability to reconnect the database' do
14
+ store.should_receive(:with_database_reconnect_and_retry)
15
+ store.deliverable_notifications(app)
16
+ end
17
+
18
+ it 'loads notifications in batches' do
19
+ Rapns.config.batch_size = 5000
20
+ Rapns.config.push = false
21
+ relation = stub.as_null_object
22
+ relation.should_receive(:limit).with(5000)
23
+ Rapns::Notification.stub(:ready_for_delivery => relation)
24
+ store.deliverable_notifications([app])
25
+ end
26
+
27
+ it 'does not load notification in batches if in push mode' do
28
+ Rapns.config.push = true
29
+ relation = stub.as_null_object
30
+ relation.should_not_receive(:limit)
31
+ Rapns::Notification.stub(:ready_for_delivery => relation)
32
+ store.deliverable_notifications([app])
33
+ end
34
+
35
+ it 'loads an undelivered notification without deliver_after set' do
36
+ notification.update_attributes!(:delivered => false, :deliver_after => nil)
37
+ store.deliverable_notifications([app]).should == [notification]
38
+ end
39
+
40
+ it 'loads an notification with a deliver_after time in the past' do
41
+ notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
42
+ store.deliverable_notifications([app]).should == [notification]
43
+ end
44
+
45
+ it 'does not load an notification with a deliver_after time in the future' do
46
+ notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
47
+ store.deliverable_notifications([app]).should be_empty
48
+ end
49
+
50
+ it 'does not load a previously delivered notification' do
51
+ notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
52
+ store.deliverable_notifications([app]).should be_empty
53
+ end
54
+
55
+ it "does not enqueue a notification that has previously failed delivery" do
56
+ notification.update_attributes!(:delivered => false, :failed => true)
57
+ store.deliverable_notifications([app]).should be_empty
58
+ end
59
+
60
+ it 'does not load notifications for apps that are still processing the previous batch' do
61
+ notification
62
+ store.deliverable_notifications([]).should be_empty
63
+ end
64
+ end
65
+
66
+ describe 'retry_after' do
67
+ it 'increments the retry count' do
68
+ expect do
69
+ store.retry_after(notification, now)
70
+ end.to change(notification, :retries).by(1)
71
+ end
72
+
73
+ it 'sets the deliver after timestamp' do
74
+ deliver_after = now + 10.seconds
75
+ expect do
76
+ store.retry_after(notification, deliver_after)
77
+ end.to change(notification, :deliver_after).to(deliver_after)
78
+ end
79
+
80
+ it 'saves the notification without validation' do
81
+ notification.should_receive(:save!).with(:validate => false)
82
+ store.retry_after(notification, now)
83
+ end
84
+ end
85
+
86
+ describe 'mark_delivered' do
87
+ it 'marks the notification as delivered' do
88
+ expect do
89
+ store.mark_delivered(notification)
90
+ end.to change(notification, :delivered).to(true)
91
+ end
92
+
93
+ it 'sets the time the notification was delivered' do
94
+ expect do
95
+ store.mark_delivered(notification)
96
+ end.to change(notification, :delivered_at).to(now)
97
+ end
98
+
99
+ it 'saves the notification without validation' do
100
+ notification.should_receive(:save!).with(:validate => false)
101
+ store.mark_delivered(notification)
102
+ end
103
+ end
104
+
105
+ describe 'mark_failed' do
106
+ it 'marks the notification as not delivered' do
107
+ store.mark_failed(notification, nil, '')
108
+ notification.delivered.should be_false
109
+ end
110
+
111
+ it 'marks the notification as failed' do
112
+ expect do
113
+ store.mark_failed(notification, nil, '')
114
+ end.to change(notification, :failed).to(true)
115
+ end
116
+
117
+ it 'sets the time the notification delivery failed' do
118
+ expect do
119
+ store.mark_failed(notification, nil, '')
120
+ end.to change(notification, :failed_at).to(now)
121
+ end
122
+
123
+ it 'sets the error code' do
124
+ expect do
125
+ store.mark_failed(notification, 42, '')
126
+ end.to change(notification, :error_code).to(42)
127
+ end
128
+
129
+ it 'sets the error description' do
130
+ expect do
131
+ store.mark_failed(notification, 42, 'Weeee')
132
+ end.to change(notification, :error_description).to('Weeee')
133
+ end
134
+
135
+ it 'saves the notification without validation' do
136
+ notification.should_receive(:save!).with(:validate => false)
137
+ store.mark_failed(notification, nil, '')
138
+ end
139
+ end
140
+
141
+ describe 'create_apns_feedback' do
142
+ it 'creates the Feedback record' do
143
+ Rapns::Apns::Feedback.should_receive(:create!).with(
144
+ :failed_at => now, :device_token => 'ab' * 32, :app => app)
145
+ store.create_apns_feedback(now, 'ab' * 32, app)
146
+ end
147
+ end
148
+
149
+ describe 'create_gcm_notification' do
150
+ let(:data) { { :data => true } }
151
+ let(:attributes) { { :device_token => 'ab' * 32 } }
152
+ let(:registration_ids) { ['123', '456'] }
153
+ let(:deliver_after) { now + 10.seconds }
154
+ let(:args) { [attributes, data, registration_ids, deliver_after, app] }
155
+
156
+ it 'sets the given attributes' do
157
+ new_notification = store.create_gcm_notification(*args)
158
+ new_notification.device_token.should == 'ab' * 32
159
+ end
160
+
161
+ it 'sets the given data' do
162
+ new_notification = store.create_gcm_notification(*args)
163
+ new_notification.data['data'].should be_true
164
+ end
165
+
166
+ it 'sets the given registration IDs' do
167
+ new_notification = store.create_gcm_notification(*args)
168
+ new_notification.registration_ids.should == registration_ids
169
+ end
170
+
171
+ it 'sets the deliver_after timestamp' do
172
+ new_notification = store.create_gcm_notification(*args)
173
+ new_notification.deliver_after.should == deliver_after
174
+ end
175
+
176
+ it 'saves the new notification' do
177
+ new_notification = store.create_gcm_notification(*args)
178
+ new_notification.new_record?.should be_false
179
+ end
180
+ end
181
+ end
@@ -1,4 +1,5 @@
1
1
  require 'unit_spec_helper'
2
+ require 'rapns/daemon/store/active_record'
2
3
 
3
4
  describe Rapns::Daemon, "when starting" do
4
5
  module Rails; end
@@ -6,27 +7,34 @@ describe Rapns::Daemon, "when starting" do
6
7
  let(:certificate) { stub }
7
8
  let(:password) { stub }
8
9
  let(:config) { stub(:pid_file => nil, :airbrake_notify => false,
9
- :foreground => true, :embedded => false, :push => false) }
10
+ :foreground => true, :embedded => false, :push => false, :store => :active_record) }
10
11
  let(:logger) { stub(:logger, :info => nil, :error => nil, :warn => nil) }
11
12
 
12
13
  before do
13
- Rapns.stub(:config => config)
14
- Rapns::Logger.stub(:new => logger)
14
+ Rapns.stub(:config => config, :logger => logger)
15
15
  Rapns::Daemon::Feeder.stub(:start)
16
16
  Rapns::Daemon::AppRunner.stub(:sync => nil, :stop => nil)
17
- Rapns::Daemon.stub(:daemonize => nil, :reconnect_database => nil, :exit => nil, :puts => nil)
17
+ Rapns::Daemon.stub(:daemonize => nil, :exit => nil, :puts => nil)
18
18
  File.stub(:open)
19
19
  Rails.stub(:root).and_return("/rails_root")
20
20
  end
21
21
 
22
- unless defined?(JRUBY_VERSION)
22
+ unless Rapns.jruby?
23
23
  it "forks into a daemon if the foreground option is false" do
24
24
  config.stub(:foreground => false)
25
- ActiveRecord::Base.stub(:establish_connection)
25
+ Rapns::Daemon.initialize_store
26
+ Rapns::Daemon.store.stub(:after_daemonize => nil)
26
27
  Rapns::Daemon.should_receive(:daemonize)
27
28
  Rapns::Daemon.start
28
29
  end
29
30
 
31
+ it 'notifies the store after forking' do
32
+ config.stub(:foreground => false)
33
+ Rapns::Daemon.initialize_store
34
+ Rapns::Daemon.store.should_receive(:after_daemonize)
35
+ Rapns::Daemon.start
36
+ end
37
+
30
38
  it "does not fork into a daemon if the foreground option is true" do
31
39
  config.stub(:foreground => true)
32
40
  Rapns::Daemon.should_not_receive(:daemonize)
@@ -57,6 +65,18 @@ describe Rapns::Daemon, "when starting" do
57
65
  Rapns::Daemon.start
58
66
  end
59
67
 
68
+ it 'instantiates the store' do
69
+ config.stub(:store => :active_record)
70
+ Rapns::Daemon.start
71
+ Rapns::Daemon.store.should be_kind_of(Rapns::Daemon::Store::ActiveRecord)
72
+ end
73
+
74
+ it 'logs an error if the store cannot be loaded' do
75
+ config.stub(:store => :foo_bar)
76
+ Rapns.logger.should_receive(:error).with(kind_of(LoadError))
77
+ Rapns::Daemon.start
78
+ end
79
+
60
80
  it "writes the process ID to the PID file" do
61
81
  Rapns::Daemon.should_receive(:write_pid_file)
62
82
  Rapns::Daemon.start
@@ -91,7 +111,7 @@ describe Rapns::Daemon, "when being shutdown" do
91
111
  end
92
112
 
93
113
  # These tests do not work on JRuby.
94
- unless defined? JRUBY_VERSION
114
+ unless Rapns.jruby?
95
115
  it "shuts down when signaled signaled SIGINT" do
96
116
  Rapns::Daemon.setup_signal_traps
97
117
  Rapns::Daemon.should_receive(:shutdown)
@@ -27,7 +27,7 @@ describe Rapns::Gcm::Notification do
27
27
  it 'num of registration Ids limit of 1000' do
28
28
  notification.registration_ids = ['a']*(1000+1)
29
29
  notification.valid?.should be_false
30
- notification.errors[:base].should == ["GCM notification num of registration_ids cannot be larger than 1000."]
30
+ notification.errors[:base].should == ["GCM notification number of registration_ids cannot be larger than 1000."]
31
31
  end
32
32
 
33
33
  it 'allows assignment of a single registration ID' do
@@ -45,15 +45,8 @@ describe Rapns::Gcm::Notification do
45
45
  notification.errors[:expiry].should == ['must be set when using a collapse_key']
46
46
  end
47
47
 
48
- it 'does not include time_to_live in the payload if collapse_key is not set' do
48
+ it 'includes time_to_live in the payload' do
49
49
  notification.expiry = 100
50
- notification.collapse_key = nil
51
- notification.as_json.key?('time_to_live').should be_false
52
- end
53
-
54
- it 'includes time_to_live in the payload if collapse_key is set' do
55
- notification.expiry = 100
56
- notification.collapse_key = 'sync'
57
50
  notification.as_json['time_to_live'].should == 100
58
51
  end
59
52
  end
@@ -12,6 +12,11 @@ describe Rapns, 'push' do
12
12
  Rapns.config.push.should be_true
13
13
  end
14
14
 
15
+ it 'initializes the store' do
16
+ Rapns::Daemon.should_receive(:initialize_store)
17
+ Rapns.push
18
+ end
19
+
15
20
  it 'syncs the app runner' do
16
21
  Rapns::Daemon::AppRunner.should_receive(:sync)
17
22
  Rapns.push
@@ -12,10 +12,6 @@ describe Rapns do
12
12
  end
13
13
  end
14
14
 
15
- # :apns_feedback, :notification_enqueued, :notification_delivered,
16
- # :notification_failed, :notification_will_retry, :apns_connection_lost,
17
- # :error
18
-
19
15
  describe Rapns::Reflections do
20
16
  it 'dispatches the given reflection' do
21
17
  did_yield = false
@@ -72,7 +72,10 @@ RSpec.configure do |config|
72
72
  DatabaseCleaner.clean
73
73
  end
74
74
 
75
- config.after(:each) { Rapns.logger = nil }
75
+ config.after(:each) do
76
+ Rapns.logger = nil
77
+ Rapns::Daemon.store = nil
78
+ end
76
79
  end
77
80
 
78
81
  # a test certificate that contains both an X509 certificate and
metadata CHANGED
@@ -1,85 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapns
3
3
  version: !ruby/object:Gem::Version
4
+ version: 3.3.0
4
5
  prerelease:
5
- version: 3.2.0
6
6
  platform: java
7
7
  authors:
8
8
  - Ian Leitch
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-02 00:00:00.000000000 Z
12
+ date: 2013-04-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: multi_json
16
- version_requirements: !ruby/object:Gem::Requirement
15
+ requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
17
  - - "~>"
19
18
  - !ruby/object:Gem::Version
20
19
  version: '1.0'
21
20
  none: false
22
- requirement: !ruby/object:Gem::Requirement
21
+ prerelease: false
22
+ name: multi_json
23
+ version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - "~>"
25
26
  - !ruby/object:Gem::Version
26
27
  version: '1.0'
27
28
  none: false
28
- prerelease: false
29
29
  type: :runtime
30
30
  - !ruby/object:Gem::Dependency
31
- name: net-http-persistent
32
- version_requirements: !ruby/object:Gem::Requirement
31
+ requirement: !ruby/object:Gem::Requirement
33
32
  requirements:
34
33
  - - ">="
35
34
  - !ruby/object:Gem::Version
36
35
  version: !binary |-
37
36
  MA==
38
37
  none: false
39
- requirement: !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ name: net-http-persistent
40
+ version_requirements: !ruby/object:Gem::Requirement
40
41
  requirements:
41
42
  - - ">="
42
43
  - !ruby/object:Gem::Version
43
44
  version: !binary |-
44
45
  MA==
45
46
  none: false
46
- prerelease: false
47
47
  type: :runtime
48
48
  - !ruby/object:Gem::Dependency
49
- name: jruby-openssl
50
- version_requirements: !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
51
50
  requirements:
52
51
  - - ">="
53
52
  - !ruby/object:Gem::Version
54
53
  version: !binary |-
55
54
  MA==
56
55
  none: false
57
- requirement: !ruby/object:Gem::Requirement
56
+ prerelease: false
57
+ name: jruby-openssl
58
+ version_requirements: !ruby/object:Gem::Requirement
58
59
  requirements:
59
60
  - - ">="
60
61
  - !ruby/object:Gem::Version
61
62
  version: !binary |-
62
63
  MA==
63
64
  none: false
64
- prerelease: false
65
65
  type: :runtime
66
66
  - !ruby/object:Gem::Dependency
67
- name: activerecord-jdbc-adapter
68
- version_requirements: !ruby/object:Gem::Requirement
67
+ requirement: !ruby/object:Gem::Requirement
69
68
  requirements:
70
69
  - - ">="
71
70
  - !ruby/object:Gem::Version
72
71
  version: !binary |-
73
72
  MA==
74
73
  none: false
75
- requirement: !ruby/object:Gem::Requirement
74
+ prerelease: false
75
+ name: activerecord-jdbc-adapter
76
+ version_requirements: !ruby/object:Gem::Requirement
76
77
  requirements:
77
78
  - - ">="
78
79
  - !ruby/object:Gem::Version
79
80
  version: !binary |-
80
81
  MA==
81
82
  none: false
82
- prerelease: false
83
83
  type: :runtime
84
84
  description: Professional grade APNs and GCM for Ruby
85
85
  email:
@@ -118,7 +118,6 @@ files:
118
118
  - lib/rapns/daemon/apns/disconnection_error.rb
119
119
  - lib/rapns/daemon/apns/feedback_receiver.rb
120
120
  - lib/rapns/daemon/app_runner.rb
121
- - lib/rapns/daemon/database_reconnectable.rb
122
121
  - lib/rapns/daemon/delivery.rb
123
122
  - lib/rapns/daemon/delivery_error.rb
124
123
  - lib/rapns/daemon/delivery_handler.rb
@@ -131,6 +130,8 @@ files:
131
130
  - lib/rapns/daemon/gcm/delivery_handler.rb
132
131
  - lib/rapns/daemon/interruptible_sleep.rb
133
132
  - lib/rapns/daemon/reflectable.rb
133
+ - lib/rapns/daemon/store/active_record.rb
134
+ - lib/rapns/daemon/store/active_record/reconnectable.rb
134
135
  - lib/rapns/deprecatable.rb
135
136
  - lib/rapns/deprecation.rb
136
137
  - lib/rapns/embed.rb
@@ -172,7 +173,6 @@ files:
172
173
  - spec/unit/daemon/apns/feedback_receiver_spec.rb
173
174
  - spec/unit/daemon/app_runner_shared.rb
174
175
  - spec/unit/daemon/app_runner_spec.rb
175
- - spec/unit/daemon/database_reconnectable_spec.rb
176
176
  - spec/unit/daemon/delivery_error_spec.rb
177
177
  - spec/unit/daemon/delivery_handler_shared.rb
178
178
  - spec/unit/daemon/delivery_queue_spec.rb
@@ -182,6 +182,8 @@ files:
182
182
  - spec/unit/daemon/gcm/delivery_spec.rb
183
183
  - spec/unit/daemon/interruptible_sleep_spec.rb
184
184
  - spec/unit/daemon/reflectable_spec.rb
185
+ - spec/unit/daemon/store/active_record/reconnectable_spec.rb
186
+ - spec/unit/daemon/store/active_record_spec.rb
185
187
  - spec/unit/daemon_spec.rb
186
188
  - spec/unit/deprecatable_spec.rb
187
189
  - spec/unit/deprecation_spec.rb
@@ -207,21 +209,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
207
209
  requirements:
208
210
  - - ">="
209
211
  - !ruby/object:Gem::Version
210
- segments:
211
- - 0
212
212
  hash: 2
213
213
  version: !binary |-
214
214
  MA==
215
+ segments:
216
+ - 0
215
217
  none: false
216
218
  required_rubygems_version: !ruby/object:Gem::Requirement
217
219
  requirements:
218
220
  - - ">="
219
221
  - !ruby/object:Gem::Version
220
- segments:
221
- - 0
222
222
  hash: 2
223
223
  version: !binary |-
224
224
  MA==
225
+ segments:
226
+ - 0
225
227
  none: false
226
228
  requirements: []
227
229
  rubyforge_project:
@@ -251,7 +253,6 @@ test_files:
251
253
  - spec/unit/daemon/apns/feedback_receiver_spec.rb
252
254
  - spec/unit/daemon/app_runner_shared.rb
253
255
  - spec/unit/daemon/app_runner_spec.rb
254
- - spec/unit/daemon/database_reconnectable_spec.rb
255
256
  - spec/unit/daemon/delivery_error_spec.rb
256
257
  - spec/unit/daemon/delivery_handler_shared.rb
257
258
  - spec/unit/daemon/delivery_queue_spec.rb
@@ -261,6 +262,8 @@ test_files:
261
262
  - spec/unit/daemon/gcm/delivery_spec.rb
262
263
  - spec/unit/daemon/interruptible_sleep_spec.rb
263
264
  - spec/unit/daemon/reflectable_spec.rb
265
+ - spec/unit/daemon/store/active_record/reconnectable_spec.rb
266
+ - spec/unit/daemon/store/active_record_spec.rb
264
267
  - spec/unit/daemon_spec.rb
265
268
  - spec/unit/deprecatable_spec.rb
266
269
  - spec/unit/deprecation_spec.rb