rapns 1.0.7 → 2.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/LICENSE +7 -0
  3. data/README.md +58 -41
  4. data/bin/rapns +23 -5
  5. data/lib/generators/rapns_generator.rb +2 -4
  6. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  7. data/lib/generators/templates/create_rapns_apps.rb +15 -0
  8. data/lib/rapns/app.rb +9 -0
  9. data/lib/rapns/daemon/app_runner.rb +131 -0
  10. data/lib/rapns/daemon/connection.rb +5 -3
  11. data/lib/rapns/daemon/delivery_handler.rb +13 -15
  12. data/lib/rapns/daemon/delivery_handler_pool.rb +8 -10
  13. data/lib/rapns/daemon/delivery_queue.rb +36 -4
  14. data/lib/rapns/daemon/feedback_receiver.rb +19 -12
  15. data/lib/rapns/daemon/feeder.rb +8 -10
  16. data/lib/rapns/daemon/logger.rb +5 -3
  17. data/lib/rapns/daemon.rb +52 -38
  18. data/lib/rapns/notification.rb +16 -5
  19. data/lib/rapns/patches.rb +2 -2
  20. data/lib/rapns/version.rb +1 -1
  21. data/lib/rapns.rb +2 -1
  22. data/spec/rapns/daemon/app_runner_spec.rb +207 -0
  23. data/spec/rapns/daemon/connection_spec.rb +177 -236
  24. data/spec/rapns/daemon/delivery_handler_pool_spec.rb +10 -14
  25. data/spec/rapns/daemon/delivery_handler_spec.rb +92 -79
  26. data/spec/rapns/daemon/feedback_receiver_spec.rb +29 -23
  27. data/spec/rapns/daemon/feeder_spec.rb +40 -44
  28. data/spec/rapns/daemon/logger_spec.rb +21 -3
  29. data/spec/rapns/daemon_spec.rb +65 -125
  30. data/spec/rapns/notification_spec.rb +16 -0
  31. data/spec/spec_helper.rb +4 -1
  32. metadata +14 -15
  33. data/History.md +0 -5
  34. data/lib/generators/templates/rapns.yml +0 -31
  35. data/lib/rapns/daemon/certificate.rb +0 -27
  36. data/lib/rapns/daemon/configuration.rb +0 -98
  37. data/lib/rapns/daemon/pool.rb +0 -36
  38. data/spec/rapns/daemon/certificate_spec.rb +0 -22
  39. data/spec/rapns/daemon/configuration_spec.rb +0 -231
@@ -1,178 +1,191 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::DeliveryHandler do
4
- let(:delivery_handler) { Rapns::Daemon::DeliveryHandler.new(0) }
4
+ let(:queue) { Rapns::Daemon::DeliveryQueue.new }
5
+ let(:name) { 'my_app:0' }
6
+ let(:host) { 'localhost' }
7
+ let(:port) { 2195 }
8
+ let(:certificate) { stub }
9
+ let(:password) { stub }
10
+ let(:delivery_handler) { Rapns::Daemon::DeliveryHandler.new(queue, name, host, port, certificate, password) }
11
+ let(:connection) { stub(:select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
12
+ let(:logger) { stub(:error => nil, :info => nil) }
13
+ let(:notification) { stub.as_null_object }
14
+ let(:config) { stub(:check_for_errors => true) }
15
+ let(:delivery_queues) { [] }
5
16
 
6
17
  before do
7
- @notification = Rapns::Notification.create!(:device_token => "a" * 64)
8
- Rapns::Daemon.stub(:delivery_queue).and_return(Rapns::Daemon::DeliveryQueue.new)
9
- Rapns::Daemon.delivery_queue.push(@notification)
10
- @connection = mock("Connection", :connect => nil, :write => nil, :close => nil, :select => nil, :read => nil)
11
- Rapns::Daemon::Connection.stub(:new).and_return(@connection)
12
- configuration = mock("Configuration", :push => stub(:host => "gateway.push.apple.com", :port => 2195))
13
- Rapns::Daemon.stub(:configuration).and_return(configuration)
14
- @logger = mock("Logger", :error => nil, :info => nil)
15
- Rapns::Daemon.stub(:logger).and_return(@logger)
18
+ Rapns::Daemon::Connection.stub(:new => connection)
19
+ Rapns::Daemon.stub(:delivery_queues => delivery_queues, :logger => logger, :config => config)
20
+ queue.push(notification)
16
21
  end
17
22
 
18
23
  it "instantiates a new connection" do
19
- Rapns::Daemon::Connection.should_receive(:new).with('DeliveryHandler 0', 'gateway.push.apple.com', 2195)
24
+ Rapns::Daemon::Connection.should_receive(:new).with("DeliveryHandler:#{name}", host, port, certificate, password)
20
25
  delivery_handler
21
26
  end
22
27
 
23
28
  it "connects the socket when started" do
24
- @connection.should_receive(:connect)
29
+ connection.should_receive(:connect)
25
30
  delivery_handler.start
26
31
  delivery_handler.stop
27
32
  end
28
33
 
29
- it "pushes a STOP instruction into the queue when told to stop" do
30
- Rapns::Daemon.delivery_queue.should_receive(:push).with(Rapns::Daemon::DeliveryHandler::STOP)
34
+ it "instructs the queue to wakeup the thread when told to stop" do
35
+ thread = stub
36
+ Thread.stub(:new => thread)
37
+ queue.should_receive(:wakeup).with(thread)
38
+ delivery_handler.start
31
39
  delivery_handler.stop
32
40
  end
33
41
 
34
- it "closes the connection when a STOP instruction is received" do
35
- Rapns::Daemon.delivery_queue.push(Rapns::Daemon::DeliveryHandler::STOP)
42
+ it "sends the binary version of the notification" do
43
+ notification.stub(:to_binary => "hi mom")
44
+ connection.should_receive(:write).with("hi mom")
36
45
  delivery_handler.send(:handle_next_notification)
37
46
  end
38
47
 
39
- it "should pop a new notification from the delivery queue" do
40
- Rapns::Daemon.delivery_queue.should_receive(:pop)
48
+ it "logs the notification delivery" do
49
+ notification.stub(:id => 666, :device_token => 'abc123')
50
+ logger.should_receive(:info).with("[DeliveryHandler:my_app:0] 666 sent to abc123")
41
51
  delivery_handler.send(:handle_next_notification)
42
52
  end
43
53
 
44
- it "does not attempt to deliver a notification when a STOP instruction is received" do
45
- Rapns::Daemon.delivery_queue.pop # empty the queue
46
- delivery_handler.should_not_receive(:deliver)
47
- Rapns::Daemon.delivery_queue.push(Rapns::Daemon::DeliveryHandler::STOP)
54
+ it "marks the notification as delivered" do
55
+ notification.should_receive(:delivered=).with(true)
48
56
  delivery_handler.send(:handle_next_notification)
49
57
  end
50
58
 
51
- it "should send the binary version of the notification" do
52
- @notification.stub((:to_binary)).and_return("hi mom")
53
- @connection.should_receive(:write).with("hi mom")
59
+ it "sets the time the notification was delivered" do
60
+ now = Time.now
61
+ Time.stub(:now).and_return(now)
62
+ notification.should_receive(:delivered_at=).with(now)
54
63
  delivery_handler.send(:handle_next_notification)
55
64
  end
56
65
 
57
- it "should log the notification delivery" do
58
- Rapns::Daemon.logger.should_receive(:info).with("Notification #{@notification.id} delivered to #{@notification.device_token}")
66
+ it "does not trigger validations when saving the notification" do
67
+ notification.should_receive(:save!).with(:validate => false)
59
68
  delivery_handler.send(:handle_next_notification)
60
69
  end
61
70
 
62
- it "should mark the notification as delivered" do
63
- expect { delivery_handler.send(:handle_next_notification); @notification.reload }.to change(@notification, :delivered).to(true)
64
- end
65
-
66
- it "should set the time the notification was delivered" do
67
- @notification.delivered_at.should be_nil
71
+ it "updates notification with the ability to reconnect the database" do
72
+ delivery_handler.should_receive(:with_database_reconnect_and_retry)
68
73
  delivery_handler.send(:handle_next_notification)
69
- @notification.reload
70
- @notification.delivered_at.should be_kind_of(Time)
71
74
  end
72
75
 
73
- it "should not trigger validations when saving the notification" do
74
- @notification.should_receive(:save!).with(:validate => false)
76
+ it "logs if an error is raised when updating the notification" do
77
+ e = StandardError.new("bork!")
78
+ notification.stub(:save!).and_raise(e)
79
+ Rapns::Daemon.logger.should_receive(:error).with(e)
75
80
  delivery_handler.send(:handle_next_notification)
76
81
  end
77
82
 
78
- it "should update notification with the ability to reconnect the database" do
79
- delivery_handler.should_receive(:with_database_reconnect_and_retry)
83
+ it "notifies the delivery queue the notification has been processed" do
84
+ queue.should_receive(:notification_processed)
80
85
  delivery_handler.send(:handle_next_notification)
81
86
  end
82
87
 
83
- it "should log if an error is raised when updating the notification" do
84
- e = StandardError.new("bork!")
85
- @notification.stub(:save!).and_raise(e)
86
- Rapns::Daemon.logger.should_receive(:error).with(e)
88
+ it 'does not check for errors if check_for_errors config option is false' do
89
+ config.stub(:check_for_errors => false)
90
+ delivery_handler.should_not_receive(:check_for_error)
87
91
  delivery_handler.send(:handle_next_notification)
88
92
  end
89
93
 
90
- it "should notify the delivery queue the notification has been processed" do
91
- Rapns::Daemon.delivery_queue.should_receive(:notification_processed)
92
- delivery_handler.send(:handle_next_notification)
94
+ describe "when being stopped" do
95
+ before { queue.pop }
96
+
97
+ it "closes the connection when a DeliveryQueue::WakeupError is raised" do
98
+ connection.should_receive(:close)
99
+ queue.stub(:pop).and_raise(Rapns::Daemon::DeliveryQueue::WakeupError)
100
+ delivery_handler.send(:handle_next_notification)
101
+ end
102
+
103
+ it "does not attempt to deliver a notification when a DeliveryQueue::::WakeupError is raised" do
104
+ queue.stub(:pop).and_raise(Rapns::Daemon::DeliveryQueue::WakeupError)
105
+ delivery_handler.should_not_receive(:deliver)
106
+ delivery_handler.send(:handle_next_notification)
107
+ end
93
108
  end
94
109
 
95
110
  describe "when delivery fails" do
96
- before do
97
- @connection.stub(:select => true, :read => [8, 4, 69].pack("ccN"), :reconnect => nil)
98
- end
111
+ before { connection.stub(:select => true, :read => [8, 4, 69].pack("ccN")) }
99
112
 
100
- it "should update notification with the ability to reconnect the database" do
113
+ it "updates notification with the ability to reconnect the database" do
101
114
  delivery_handler.should_receive(:with_database_reconnect_and_retry)
102
115
  delivery_handler.send(:handle_next_notification)
103
116
  end
104
117
 
105
- it "should set the notification as not delivered" do
106
- @notification.should_receive(:delivered=).with(false)
118
+ it "sets the notification as not delivered" do
119
+ notification.should_receive(:delivered=).with(false)
107
120
  delivery_handler.send(:handle_next_notification)
108
121
  end
109
122
 
110
- it "should set the notification delivered_at timestamp to nil" do
111
- @notification.should_receive(:delivered_at=).with(nil)
123
+ it "sets the notification delivered_at timestamp to nil" do
124
+ notification.should_receive(:delivered_at=).with(nil)
112
125
  delivery_handler.send(:handle_next_notification)
113
126
  end
114
127
 
115
- it "should set the notification as failed" do
116
- @notification.should_receive(:failed=).with(true)
128
+ it "sets the notification as failed" do
129
+ notification.should_receive(:failed=).with(true)
117
130
  delivery_handler.send(:handle_next_notification)
118
131
  end
119
132
 
120
- it "should set the notification failed_at timestamp" do
133
+ it "sets the notification failed_at timestamp" do
121
134
  now = Time.now
122
135
  Time.stub(:now).and_return(now)
123
- @notification.should_receive(:failed_at=).with(now)
136
+ notification.should_receive(:failed_at=).with(now)
124
137
  delivery_handler.send(:handle_next_notification)
125
138
  end
126
139
 
127
- it "should set the notification error code" do
128
- @notification.should_receive(:error_code=).with(4)
140
+ it "sets the notification error code" do
141
+ notification.should_receive(:error_code=).with(4)
129
142
  delivery_handler.send(:handle_next_notification)
130
143
  end
131
144
 
132
- it "should log the delivery error" do
145
+ it "logs the delivery error" do
133
146
  error = Rapns::DeliveryError.new(4, 12, "Missing payload")
134
147
  Rapns::DeliveryError.stub(:new => error)
135
- Rapns::Daemon.logger.should_receive(:error).with(error)
148
+ logger.should_receive(:error).with(error)
136
149
  delivery_handler.send(:handle_next_notification)
137
150
  end
138
151
 
139
- it "should set the notification error description" do
140
- @notification.should_receive(:error_description=).with("Missing payload")
152
+ it "sets the notification error description" do
153
+ notification.should_receive(:error_description=).with("Missing payload")
141
154
  delivery_handler.send(:handle_next_notification)
142
155
  end
143
156
 
144
- it "should skip validation when saving the notification" do
145
- @notification.should_receive(:save!).with(:validate => false)
157
+ it "skips validation when saving the notification" do
158
+ notification.should_receive(:save!).with(:validate => false)
146
159
  delivery_handler.send(:handle_next_notification)
147
160
  end
148
161
 
149
- it "should read 6 bytes from the socket" do
150
- @connection.should_receive(:read).with(6).and_return(nil)
162
+ it "reads 6 bytes from the socket" do
163
+ connection.should_receive(:read).with(6).and_return(nil)
151
164
  delivery_handler.send(:handle_next_notification)
152
165
  end
153
166
 
154
- it "should not attempt to read from the socket if the socket was not selected for reading after the timeout" do
155
- @connection.stub(:select => nil)
156
- @connection.should_not_receive(:read)
167
+ it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
168
+ connection.stub(:select => nil)
169
+ connection.should_not_receive(:read)
157
170
  delivery_handler.send(:handle_next_notification)
158
171
  end
159
172
 
160
- it "should reconnect the socket" do
161
- @connection.should_receive(:reconnect)
173
+ it "reconnects the socket" do
174
+ connection.should_receive(:reconnect)
162
175
  delivery_handler.send(:handle_next_notification)
163
176
  end
164
177
 
165
- it "should log that the connection is being reconnected" do
166
- Rapns::Daemon.logger.should_receive(:error).with("[DeliveryHandler 0] Error received, reconnecting...")
178
+ it "logs that the connection is being reconnected" do
179
+ Rapns::Daemon.logger.should_receive(:error).with("[DeliveryHandler:my_app:0] Error received, reconnecting...")
167
180
  delivery_handler.send(:handle_next_notification)
168
181
  end
169
182
 
170
183
  context "when the APNs disconnects without returning an error" do
171
184
  before do
172
- @connection.stub(:read => nil)
185
+ connection.stub(:read => nil)
173
186
  end
174
187
 
175
- it 'should raise a DisconnectError error if the connection is closed without an error being returned' do
188
+ it 'raises a DisconnectError error if the connection is closed without an error being returned' do
176
189
  error = Rapns::DisconnectionError.new
177
190
  Rapns::DisconnectionError.should_receive(:new).and_return(error)
178
191
  Rapns::Daemon.logger.should_receive(:error).with(error)
@@ -180,12 +193,12 @@ describe Rapns::Daemon::DeliveryHandler do
180
193
  end
181
194
 
182
195
  it 'does not set the error code on the notification' do
183
- @notification.should_receive(:error_code=).with(nil)
196
+ notification.should_receive(:error_code=).with(nil)
184
197
  delivery_handler.send(:handle_next_notification)
185
198
  end
186
199
 
187
200
  it 'sets the error descriptipon on the notification' do
188
- @notification.should_receive(:error_description=).with("APNs disconnected without returning an error.")
201
+ notification.should_receive(:error_description=).with("APNs disconnected without returning an error.")
189
202
  delivery_handler.send(:handle_next_notification)
190
203
  end
191
204
  end
@@ -1,16 +1,22 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
4
+ let(:host) { 'feedback.push.apple.com' }
5
+ let(:port) { 2196 }
6
+ let(:poll) { 60 }
7
+ let(:certificate) { stub }
8
+ let(:password) { stub }
9
+ let(:app) { 'my_app' }
4
10
  let(:connection) { stub(:connect => nil, :read => nil, :close => nil) }
5
11
  let(:logger) { stub(:error => nil, :info => nil) }
12
+ let(:receiever) { Rapns::Daemon::FeedbackReceiver.new(app, host, port, poll, certificate, password) }
6
13
 
7
14
  before do
8
- Rapns::Daemon::FeedbackReceiver.stub(:interruptible_sleep)
15
+ receiever.stub(:interruptible_sleep)
9
16
  Rapns::Daemon.logger = logger
10
17
  Rapns::Daemon::Connection.stub(:new => connection)
11
18
  Rapns::Feedback.stub(:create!)
12
- Rapns::Daemon.configuration = stub(:feedback => stub(:host => 'feedback.push.apple.com', :port => 2196, :poll => 60))
13
- Rapns::Daemon::FeedbackReceiver.instance_variable_set("@stop", false)
19
+ receiever.instance_variable_set("@stop", false)
14
20
  end
15
21
 
16
22
  def stub_connection_read_with_tuple
@@ -25,62 +31,62 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
25
31
  end
26
32
 
27
33
  it 'instantiates a new connection' do
28
- Rapns::Daemon::Connection.should_receive(:new).with("FeedbackReceiver", 'feedback.push.apple.com', 2196)
29
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
34
+ Rapns::Daemon::Connection.should_receive(:new).with("FeedbackReceiver:#{app}", host, port, certificate, password)
35
+ receiever.check_for_feedback
30
36
  end
31
37
 
32
38
  it 'connects to the feeback service' do
33
39
  connection.should_receive(:connect)
34
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
40
+ receiever.check_for_feedback
35
41
  end
36
42
 
37
43
  it 'closes the connection' do
38
44
  connection.should_receive(:close)
39
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
45
+ receiever.check_for_feedback
40
46
  end
41
47
 
42
48
  it 'reads from the connection' do
43
49
  connection.should_receive(:read).with(38)
44
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
50
+ receiever.check_for_feedback
45
51
  end
46
52
 
47
53
  it 'logs the feedback' do
48
54
  stub_connection_read_with_tuple
49
- Rapns::Daemon.logger.should_receive(:info).with("[FeedbackReceiver] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17")
50
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
55
+ Rapns::Daemon.logger.should_receive(:info).with("[FeedbackReceiver:my_app] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17")
56
+ receiever.check_for_feedback
51
57
  end
52
58
 
53
59
  it 'creates the feedback' do
54
60
  stub_connection_read_with_tuple
55
- Rapns::Feedback.should_receive(:create!).with(:failed_at => Time.at(1323533325), :device_token => '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17')
56
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
61
+ Rapns::Feedback.should_receive(:create!).with(:failed_at => Time.at(1323533325), :device_token => '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', :app => 'my_app')
62
+ receiever.check_for_feedback
57
63
  end
58
64
 
59
65
  it 'logs errors' do
60
66
  error = StandardError.new('bork!')
61
67
  connection.stub(:read).and_raise(error)
62
68
  Rapns::Daemon.logger.should_receive(:error).with(error)
63
- Rapns::Daemon::FeedbackReceiver.check_for_feedback
69
+ receiever.check_for_feedback
64
70
  end
65
71
 
66
72
  it 'sleeps for the feedback poll period' do
67
- Rapns::Daemon::FeedbackReceiver.stub(:check_for_feedback)
68
- Rapns::Daemon::FeedbackReceiver.should_receive(:interruptible_sleep).with(60).at_least(:once)
73
+ receiever.stub(:check_for_feedback)
74
+ receiever.should_receive(:interruptible_sleep).with(60).at_least(:once)
69
75
  Thread.stub(:new).and_yield
70
- Rapns::Daemon::FeedbackReceiver.stub(:loop).and_yield
71
- Rapns::Daemon::FeedbackReceiver.start
76
+ receiever.stub(:loop).and_yield
77
+ receiever.start
72
78
  end
73
79
 
74
80
  it 'checks for feedback when started' do
75
- Rapns::Daemon::FeedbackReceiver.should_receive(:check_for_feedback).at_least(:once)
81
+ receiever.should_receive(:check_for_feedback).at_least(:once)
76
82
  Thread.stub(:new).and_yield
77
- Rapns::Daemon::FeedbackReceiver.stub(:loop).and_yield
78
- Rapns::Daemon::FeedbackReceiver.start
83
+ receiever.stub(:loop).and_yield
84
+ receiever.start
79
85
  end
80
86
 
81
87
  it 'interrupts sleep when stopped' do
82
- Rapns::Daemon::FeedbackReceiver.stub(:check_for_feedback)
83
- Rapns::Daemon::FeedbackReceiver.should_receive(:interrupt_sleep)
84
- Rapns::Daemon::FeedbackReceiver.stop
88
+ receiever.stub(:check_for_feedback)
89
+ receiever.should_receive(:interrupt_sleep)
90
+ receiever.stop
85
91
  end
86
92
  end
@@ -1,79 +1,75 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::Feeder do
4
+ let(:poll) { 2 }
5
+ let(:config) { stub(:batch_size => 5000) }
6
+ let(:notification) { Rapns::Notification.create!(:device_token => "a" * 64, :app => 'my_app') }
7
+ let(:logger) { stub }
8
+
4
9
  before do
5
10
  Rapns::Daemon::Feeder.stub(:sleep)
6
11
  Rapns::Daemon::Feeder.stub(:interruptible_sleep)
7
- @notification = Rapns::Notification.create!(:device_token => "a" * 64)
8
- @logger = mock("Logger", :info => nil, :error => nil, :warn => nil)
9
- Rapns::Daemon.stub(:logger).and_return(@logger)
10
- @queue = mock(:push => nil, :notifications_processed? => true)
11
- Rapns::Daemon.stub(:delivery_queue).and_return(@queue)
12
- Rapns::Daemon.stub(:configuration => mock("Configuration", :push => stub(:poll => 2)))
12
+ Rapns::Daemon.stub(:logger => logger, :config => config)
13
13
  Rapns::Daemon::Feeder.instance_variable_set("@stop", false)
14
+ Rapns::Daemon::AppRunner.stub(:ready => ['my_app'])
15
+ Rapns::Daemon::AppRunner.stub(:ready => ['my_app'])
14
16
  end
15
17
 
16
- it "should reconnect to the database when daemonized" do
17
- Rapns::Daemon::Feeder.stub(:loop)
18
- Rapns::Daemon::Feeder.should_receive(:reconnect_database)
19
- Rapns::Daemon::Feeder.start(false)
20
- end
21
-
22
- it "should check for new notifications with the ability to reconnect the database" do
18
+ it "checks for new notifications with the ability to reconnect the database" do
23
19
  Rapns::Daemon::Feeder.should_receive(:with_database_reconnect_and_retry)
24
20
  Rapns::Daemon::Feeder.enqueue_notifications
25
21
  end
26
22
 
27
- it "should not reconnect to the database when running in the foreground" do
28
- Rapns::Daemon::Feeder.stub(:loop)
29
- Rapns::Daemon::Feeder.should_not_receive(:reconnect_database)
30
- Rapns::Daemon::Feeder.start(true)
23
+ it 'loads notifications in batches' do
24
+ relation = stub
25
+ relation.should_receive(:find_each).with(:batch_size => 5000)
26
+ Rapns::Notification.stub(:ready_for_delivery => relation)
27
+ Rapns::Daemon::Feeder.enqueue_notifications
31
28
  end
32
29
 
33
- it "should enqueue an undelivered notification" do
34
- @notification.update_attributes!(:delivered => false)
35
- Rapns::Daemon.delivery_queue.should_receive(:push)
30
+ it "delivers the notification" do
31
+ notification.update_attributes!(:delivered => false)
32
+ Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
36
33
  Rapns::Daemon::Feeder.enqueue_notifications
37
34
  end
38
35
 
39
- it "should enqueue an undelivered notification without deliver_after set" do
40
- @notification.update_attributes!(:delivered => false, :deliver_after => nil)
41
- Rapns::Daemon.delivery_queue.should_receive(:push)
36
+ it 'does not enqueue the notification if the app runner is still processing the previous batch' do
37
+ Rapns::Daemon::AppRunner.stub(:ready => [])
38
+ Rapns::Daemon::AppRunner.should_not_receive(:deliver)
42
39
  Rapns::Daemon::Feeder.enqueue_notifications
43
40
  end
44
41
 
45
- it "should enqueue a notification with a deliver_after time in the past" do
46
- @notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
47
- Rapns::Daemon.delivery_queue.should_receive(:push)
42
+ it "enqueues an undelivered notification without deliver_after set" do
43
+ notification.update_attributes!(:delivered => false, :deliver_after => nil)
44
+ Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
48
45
  Rapns::Daemon::Feeder.enqueue_notifications
49
46
  end
50
47
 
51
- it "should not enqueue a notification with a deliver_after time in the future" do
52
- @notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
53
- Rapns::Daemon.delivery_queue.should_not_receive(:push)
48
+ it "enqueues a notification with a deliver_after time in the past" do
49
+ notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
50
+ Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
54
51
  Rapns::Daemon::Feeder.enqueue_notifications
55
52
  end
56
53
 
57
- it "should not enqueue a previously delivered notification" do
58
- @notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
59
- Rapns::Daemon.delivery_queue.should_not_receive(:push)
54
+ it "does not enqueue a notification with a deliver_after time in the future" do
55
+ notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
56
+ Rapns::Daemon::AppRunner.should_not_receive(:deliver)
60
57
  Rapns::Daemon::Feeder.enqueue_notifications
61
58
  end
62
59
 
63
- it "should not enqueue a notification that has previously failed delivery" do
64
- @notification.update_attributes!(:delivered => false, :failed => true)
65
- Rapns::Daemon.delivery_queue.should_not_receive(:push)
60
+ it "does not enqueue a previously delivered notification" do
61
+ notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
62
+ Rapns::Daemon::AppRunner.should_not_receive(:deliver)
66
63
  Rapns::Daemon::Feeder.enqueue_notifications
67
64
  end
68
65
 
69
- it "should not enqueue more notifications if other are still being processed" do
70
- Rapns::Daemon.delivery_queue.stub(:notifications_processed? => false)
71
- Rapns::Notification.should_not_receive(:ready_for_delivery)
72
- Rapns::Daemon.delivery_queue.should_not_receive(:push)
66
+ it "does not enqueue a notification that has previously failed delivery" do
67
+ notification.update_attributes!(:delivered => false, :failed => true)
68
+ Rapns::Daemon::AppRunner.should_not_receive(:deliver)
73
69
  Rapns::Daemon::Feeder.enqueue_notifications
74
70
  end
75
71
 
76
- it "should log errors" do
72
+ it "logs errors" do
77
73
  e = StandardError.new("bork")
78
74
  Rapns::Notification.stub(:ready_for_delivery).and_raise(e)
79
75
  Rapns::Daemon.logger.should_receive(:error).with(e)
@@ -88,12 +84,12 @@ describe Rapns::Daemon::Feeder do
88
84
  it "enqueues notifications when started" do
89
85
  Rapns::Daemon::Feeder.should_receive(:enqueue_notifications).at_least(:once)
90
86
  Rapns::Daemon::Feeder.stub(:loop).and_yield
91
- Rapns::Daemon::Feeder.start(true)
87
+ Rapns::Daemon::Feeder.start(poll)
92
88
  end
93
89
 
94
- it "should sleep for the given period" do
95
- Rapns::Daemon::Feeder.should_receive(:interruptible_sleep).with(2)
90
+ it "sleeps for the given period" do
91
+ Rapns::Daemon::Feeder.should_receive(:interruptible_sleep).with(poll)
96
92
  Rapns::Daemon::Feeder.stub(:loop).and_yield
97
- Rapns::Daemon::Feeder.start(true)
93
+ Rapns::Daemon::Feeder.start(poll)
98
94
  end
99
95
  end
@@ -21,17 +21,30 @@ module Airbrake
21
21
  end
22
22
 
23
23
  describe Rapns::Daemon::Logger do
24
+ let(:log) { stub(:sync= => true) }
25
+ let(:config) { stub(:airbrake_notify => true) }
26
+
24
27
  before do
25
28
  Rails.stub(:root).and_return("/rails_root")
26
29
  @buffered_logger = mock("BufferedLogger", :info => nil, :error => nil, :level => 0, :auto_flushing => 1, :auto_flushing= => nil)
27
30
  Rails.logger = @buffered_logger
28
31
  ActiveSupport::BufferedLogger.stub(:new).and_return(@buffered_logger)
29
- configuration = mock("Configuration", :airbrake_notify? => true)
30
- Rapns::Daemon.stub(:configuration).and_return(configuration)
32
+ Rapns::Daemon.stub(:config => config)
33
+ File.stub(:open => log)
31
34
  end
32
35
 
33
36
  it "should open the a log file in the Rails log directory" do
34
- ActiveSupport::BufferedLogger.should_receive(:new).with("/rails_root/log/rapns.log", Rails.logger.level)
37
+ File.should_receive(:open).with('/rails_root/log/rapns.log', 'w')
38
+ Rapns::Daemon::Logger.new(:foreground => true)
39
+ end
40
+
41
+ it 'sets sync mode on the log descriptor' do
42
+ log.should_receive(:sync=).with(true)
43
+ Rapns::Daemon::Logger.new(:foreground => true)
44
+ end
45
+
46
+ it 'instantiates the BufferedLogger' do
47
+ ActiveSupport::BufferedLogger.should_receive(:new).with(log, Rails.logger.level)
35
48
  Rapns::Daemon::Logger.new(:foreground => true)
36
49
  end
37
50
 
@@ -69,6 +82,7 @@ describe Rapns::Daemon::Logger do
69
82
 
70
83
  it "should handle an Exception instance" do
71
84
  e = RuntimeError.new("hi mom")
85
+ e.stub(:backtrace => [])
72
86
  logger = Rapns::Daemon::Logger.new(:foreground => false)
73
87
  @buffered_logger.should_receive(:error).with(/RuntimeError, hi mom/)
74
88
  logger.error(e)
@@ -76,6 +90,7 @@ describe Rapns::Daemon::Logger do
76
90
 
77
91
  it "should notify Airbrake of the exception" do
78
92
  e = RuntimeError.new("hi mom")
93
+ e.stub(:backtrace => [])
79
94
  logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => true)
80
95
  Airbrake.should_receive(:notify_or_ignore).with(e)
81
96
  logger.error(e)
@@ -95,6 +110,7 @@ describe Rapns::Daemon::Logger do
95
110
 
96
111
  it "should notify using HoptoadNotifier" do
97
112
  e = RuntimeError.new("hi mom")
113
+ e.stub(:backtrace => [])
98
114
  logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => true)
99
115
  HoptoadNotifier.should_receive(:notify_or_ignore).with(e)
100
116
  logger.error(e)
@@ -103,6 +119,7 @@ describe Rapns::Daemon::Logger do
103
119
 
104
120
  it "should not notify Airbrake of the exception if the airbrake_notify option is false" do
105
121
  e = RuntimeError.new("hi mom")
122
+ e.stub(:backtrace => [])
106
123
  logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => false)
107
124
  Airbrake.should_not_receive(:notify_or_ignore).with(e)
108
125
  logger.error(e)
@@ -110,6 +127,7 @@ describe Rapns::Daemon::Logger do
110
127
 
111
128
  it "should not notify Airbrake if explicitly disabled in the call to error" do
112
129
  e = RuntimeError.new("hi mom")
130
+ e.stub(:backtrace => [])
113
131
  logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => true)
114
132
  Airbrake.should_not_receive(:notify_or_ignore).with(e)
115
133
  logger.error(e, :airbrake_notify => false)