rpush 2.0.0.beta1 → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rpush/daemon.rb +3 -3
- data/lib/rpush/daemon/adm/delivery.rb +6 -6
- data/lib/rpush/daemon/app_runner.rb +52 -66
- data/lib/rpush/daemon/dispatcher_loop.rb +27 -22
- data/lib/rpush/daemon/feeder.rb +1 -1
- data/lib/rpush/daemon/proc_title.rb +2 -2
- data/lib/rpush/daemon/retryable_error.rb +2 -0
- data/lib/rpush/daemon/signal_handler.rb +1 -1
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +6 -2
- data/lib/rpush/daemon/string_helpers.rb +15 -0
- data/lib/rpush/daemon/synchronizer.rb +44 -0
- data/lib/rpush/embed.rb +1 -1
- data/lib/rpush/push.rb +1 -1
- data/lib/rpush/version.rb +1 -1
- data/spec/functional/synchronization_spec.rb +46 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/client/active_record/apns/notification_spec.rb +2 -2
- data/spec/unit/daemon/adm/delivery_spec.rb +2 -2
- data/spec/unit/daemon/app_runner_spec.rb +32 -98
- data/spec/unit/daemon/dispatcher_loop_spec.rb +0 -13
- data/spec/unit/daemon/feeder_spec.rb +2 -2
- data/spec/unit/daemon/signal_handler_spec.rb +3 -3
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +1 -0
- data/spec/unit/daemon_spec.rb +3 -2
- data/spec/unit/embed_spec.rb +2 -2
- data/spec/unit/logger_spec.rb +7 -5
- data/spec/unit/push_spec.rb +4 -3
- metadata +6 -8
- data/lib/rpush/daemon/dispatcher_loop_collection.rb +0 -33
- data/lib/rpush/daemon/too_many_requests_error.rb +0 -20
- data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +0 -37
- data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09d2df386688b4c0ac01e8aab5e4c725257a3263
|
4
|
+
data.tar.gz: a7233c67417785808daf0e8d0f637d17b31a33b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e19a18011c6e4e06b84deb49b82172ebb580a71ba8aef64e7ba6dce9edfc8aa42273bc131643a1f174aa9a30429b9797617e0661f7005eb657f9d9f1daf0b76
|
7
|
+
data.tar.gz: 47c703cdd66bb3fd80327d991604d0ee573db02b4324023484a90ac5ce7793cd022906ea3b1f424c97390edf7e59e13649c41efc9f2de9cadf68859fbc937f01
|
data/lib/rpush/daemon.rb
CHANGED
@@ -8,18 +8,18 @@ require 'rpush/daemon/errors'
|
|
8
8
|
require 'rpush/daemon/constants'
|
9
9
|
require 'rpush/daemon/reflectable'
|
10
10
|
require 'rpush/daemon/loggable'
|
11
|
+
require 'rpush/daemon/string_helpers'
|
11
12
|
require 'rpush/daemon/interruptible_sleep'
|
12
13
|
require 'rpush/daemon/delivery_error'
|
13
14
|
require 'rpush/daemon/retryable_error'
|
14
|
-
require 'rpush/daemon/too_many_requests_error'
|
15
15
|
require 'rpush/daemon/delivery'
|
16
16
|
require 'rpush/daemon/feeder'
|
17
17
|
require 'rpush/daemon/batch'
|
18
18
|
require 'rpush/daemon/queue_payload'
|
19
|
+
require 'rpush/daemon/synchronizer'
|
19
20
|
require 'rpush/daemon/app_runner'
|
20
21
|
require 'rpush/daemon/tcp_connection'
|
21
22
|
require 'rpush/daemon/dispatcher_loop'
|
22
|
-
require 'rpush/daemon/dispatcher_loop_collection'
|
23
23
|
require 'rpush/daemon/dispatcher/http'
|
24
24
|
require 'rpush/daemon/dispatcher/tcp'
|
25
25
|
require 'rpush/daemon/dispatcher/apns_tcp'
|
@@ -55,7 +55,7 @@ module Rpush
|
|
55
55
|
Process.daemon if daemonize?
|
56
56
|
initialize_store
|
57
57
|
write_pid_file
|
58
|
-
|
58
|
+
Synchronizer.sync
|
59
59
|
|
60
60
|
# No further store connections will be made from this thread.
|
61
61
|
store.release_connection
|
@@ -36,10 +36,10 @@ module Rpush
|
|
36
36
|
end
|
37
37
|
mark_delivered
|
38
38
|
end
|
39
|
+
rescue Rpush::RateLimitError => error
|
40
|
+
handle_rate_limited(error)
|
39
41
|
rescue Rpush::RetryableError => error
|
40
42
|
handle_retryable(error)
|
41
|
-
rescue Rpush::TooManyRequestsError => error
|
42
|
-
handle_too_many_requests(error)
|
43
43
|
rescue StandardError => error
|
44
44
|
mark_failed(error)
|
45
45
|
raise
|
@@ -58,7 +58,7 @@ module Rpush
|
|
58
58
|
when 401
|
59
59
|
unauthorized(response)
|
60
60
|
when 429
|
61
|
-
|
61
|
+
rate_limited(response)
|
62
62
|
when 500
|
63
63
|
internal_server_error(current_registration_id)
|
64
64
|
when 503
|
@@ -94,7 +94,7 @@ module Rpush
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def handle_rate_limited(error)
|
98
98
|
if @sent_registration_ids.empty?
|
99
99
|
# none sent yet, just resend after the specified retry-after response.header
|
100
100
|
retry_delivery(@notification, error.response)
|
@@ -129,9 +129,9 @@ module Rpush
|
|
129
129
|
fail Rpush::RetryableError.new(response.code.to_i, @notification.id, 'ADM responded with an Unauthorized Error.', response)
|
130
130
|
end
|
131
131
|
|
132
|
-
def
|
132
|
+
def rate_limited(response)
|
133
133
|
# raise error so the current notification stops sending messages to remaining reg ids
|
134
|
-
fail Rpush::
|
134
|
+
fail Rpush::RateLimitError.new(response.code.to_i, @notification.id, 'Exceeded maximum allowable rate of messages.', response)
|
135
135
|
end
|
136
136
|
|
137
137
|
def internal_server_error(current_registration_id)
|
@@ -4,64 +4,73 @@ module Rpush
|
|
4
4
|
extend Reflectable
|
5
5
|
include Reflectable
|
6
6
|
include Loggable
|
7
|
-
|
8
|
-
class << self
|
9
|
-
attr_reader :runners
|
10
|
-
end
|
7
|
+
include StringHelpers
|
11
8
|
|
12
9
|
@runners = {}
|
13
10
|
|
14
11
|
def self.enqueue(notifications)
|
15
12
|
notifications.group_by(&:app_id).each do |app_id, group|
|
16
|
-
|
17
|
-
runners[app_id].enqueue(group) if runners[app_id]
|
13
|
+
start_app_with_id(app_id) unless @runners[app_id]
|
14
|
+
@runners[app_id].enqueue(group) if @runners[app_id]
|
18
15
|
end
|
16
|
+
|
19
17
|
ProcTitle.update
|
20
18
|
end
|
21
19
|
|
22
|
-
def self.
|
23
|
-
|
24
|
-
apps.each { |app| sync_app(app) }
|
25
|
-
removed = runners.keys - apps.map(&:id)
|
26
|
-
removed.each { |app_id| runners.delete(app_id).stop }
|
27
|
-
ProcTitle.update
|
20
|
+
def self.start_app_with_id(app_id)
|
21
|
+
start_app(Rpush::Daemon.store.app(app_id))
|
28
22
|
end
|
29
23
|
|
30
|
-
def self.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
rescue StandardError => e
|
39
|
-
Rpush.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
40
|
-
Rpush.logger.error(e)
|
41
|
-
reflect(:error, e)
|
42
|
-
end
|
43
|
-
end
|
24
|
+
def self.start_app(app)
|
25
|
+
@runners[app.id] = new(app)
|
26
|
+
@runners[app.id].start
|
27
|
+
rescue StandardError => e
|
28
|
+
@runners.delete(app.id)
|
29
|
+
Rpush.logger.error("[#{app.name}] Exception raised during startup. Notifications will not be delivered for this app.")
|
30
|
+
Rpush.logger.error(e)
|
31
|
+
reflect(:error, e)
|
44
32
|
end
|
45
33
|
|
46
|
-
def self.
|
47
|
-
|
34
|
+
def self.stop_app(app_id)
|
35
|
+
@runners.delete(app_id).stop
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.app_running?(app)
|
39
|
+
@runners.key?(app.id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.app_ids
|
43
|
+
@runners.keys
|
48
44
|
end
|
49
45
|
|
50
46
|
def self.stop
|
51
|
-
runners.values.map(&:stop)
|
52
|
-
runners.clear
|
47
|
+
@runners.values.map(&:stop)
|
48
|
+
@runners.clear
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.total_dispatchers
|
52
|
+
@runners.values.sum(&:num_dispatcher_loops)
|
53
53
|
end
|
54
54
|
|
55
|
-
def self.
|
56
|
-
runners.values.sum(&:
|
55
|
+
def self.total_queued
|
56
|
+
@runners.values.sum(&:queue_size)
|
57
57
|
end
|
58
58
|
|
59
|
-
def self.
|
60
|
-
runners.
|
59
|
+
def self.num_dispatchers_for_app(app)
|
60
|
+
runner = @runners[app.id]
|
61
|
+
runner ? runner.num_dispatcher_loops : 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.decrement_dispatchers(app, num)
|
65
|
+
@runners[app.id].decrement_dispatchers(num)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.increment_dispatchers(app, num)
|
69
|
+
@runners[app.id].increment_dispatchers(num)
|
61
70
|
end
|
62
71
|
|
63
72
|
def self.debug
|
64
|
-
runners.values.map(&:debug)
|
73
|
+
@runners.values.map(&:debug)
|
65
74
|
end
|
66
75
|
|
67
76
|
attr_reader :app
|
@@ -69,12 +78,12 @@ module Rpush
|
|
69
78
|
def initialize(app)
|
70
79
|
@app = app
|
71
80
|
@loops = []
|
81
|
+
@dispatcher_loops = []
|
72
82
|
end
|
73
83
|
|
74
84
|
def start
|
75
|
-
app.connections.times { dispatcher_loops.push(new_dispatcher_loop) }
|
85
|
+
app.connections.times { @dispatcher_loops.push(new_dispatcher_loop) }
|
76
86
|
start_loops
|
77
|
-
log_info("Started, #{dispatchers_str}.")
|
78
87
|
end
|
79
88
|
|
80
89
|
def stop
|
@@ -103,31 +112,18 @@ module Rpush
|
|
103
112
|
end
|
104
113
|
end
|
105
114
|
|
106
|
-
def sync(app)
|
107
|
-
@app = app
|
108
|
-
diff = dispatcher_loops.size - app.connections
|
109
|
-
return if diff == 0
|
110
|
-
if diff > 0
|
111
|
-
decrement_dispatchers(diff)
|
112
|
-
log_info("Stopped #{dispatchers_str(diff)}. #{dispatchers_str} running.")
|
113
|
-
else
|
114
|
-
increment_dispatchers(diff.abs)
|
115
|
-
log_info("Started #{dispatchers_str(diff)}. #{dispatchers_str} running.")
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
115
|
def decrement_dispatchers(num)
|
120
|
-
num.times { dispatcher_loops.pop }
|
116
|
+
num.times { @dispatcher_loops.pop.stop }
|
121
117
|
end
|
122
118
|
|
123
119
|
def increment_dispatchers(num)
|
124
|
-
num.times { dispatcher_loops.push(new_dispatcher_loop) }
|
120
|
+
num.times { @dispatcher_loops.push(new_dispatcher_loop) }
|
125
121
|
end
|
126
122
|
|
127
123
|
def debug
|
128
124
|
dispatcher_details = {}
|
129
125
|
|
130
|
-
dispatcher_loops.
|
126
|
+
@dispatcher_loops.each_with_index do |dispatcher_loop, i|
|
131
127
|
dispatcher_details[i] = {
|
132
128
|
started_at: dispatcher_loop.started_at.iso8601,
|
133
129
|
dispatched: dispatcher_loop.dispatch_count,
|
@@ -144,7 +140,7 @@ module Rpush
|
|
144
140
|
end
|
145
141
|
|
146
142
|
def num_dispatcher_loops
|
147
|
-
dispatcher_loops.size
|
143
|
+
@dispatcher_loops.size
|
148
144
|
end
|
149
145
|
|
150
146
|
private
|
@@ -160,8 +156,8 @@ module Rpush
|
|
160
156
|
end
|
161
157
|
|
162
158
|
def stop_dispatcher_loops
|
163
|
-
dispatcher_loops.stop
|
164
|
-
@dispatcher_loops
|
159
|
+
@dispatcher_loops.map(&:stop)
|
160
|
+
@dispatcher_loops.clear
|
165
161
|
end
|
166
162
|
|
167
163
|
def new_dispatcher_loop
|
@@ -179,16 +175,6 @@ module Rpush
|
|
179
175
|
def queue
|
180
176
|
@queue ||= Queue.new
|
181
177
|
end
|
182
|
-
|
183
|
-
def dispatcher_loops
|
184
|
-
@dispatcher_loops ||= Rpush::Daemon::DispatcherLoopCollection.new
|
185
|
-
end
|
186
|
-
|
187
|
-
def dispatchers_str(count = num_dispatcher_loops)
|
188
|
-
count = count.abs
|
189
|
-
str = count == 1 ? 'dispatcher' : 'dispatchers'
|
190
|
-
"#{count} #{str}"
|
191
|
-
end
|
192
178
|
end
|
193
179
|
end
|
194
180
|
end
|
@@ -6,7 +6,7 @@ module Rpush
|
|
6
6
|
|
7
7
|
attr_reader :started_at, :dispatch_count
|
8
8
|
|
9
|
-
|
9
|
+
STOP = :stop
|
10
10
|
|
11
11
|
def initialize(queue, dispatcher)
|
12
12
|
@queue = queue
|
@@ -23,8 +23,17 @@ module Rpush
|
|
23
23
|
|
24
24
|
@thread = Thread.new do
|
25
25
|
loop do
|
26
|
-
|
27
|
-
|
26
|
+
payload = @queue.pop
|
27
|
+
if stop_payload?(payload)
|
28
|
+
break if should_stop?(payload)
|
29
|
+
|
30
|
+
# Intended for another dispatcher loop.
|
31
|
+
@queue.push(payload)
|
32
|
+
Thread.pass
|
33
|
+
sleep 0.1
|
34
|
+
else
|
35
|
+
dispatch(payload)
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
Rpush::Daemon.store.release_connection
|
@@ -32,31 +41,27 @@ module Rpush
|
|
32
41
|
end
|
33
42
|
|
34
43
|
def stop
|
35
|
-
@
|
36
|
-
end
|
37
|
-
|
38
|
-
def wakeup
|
39
|
-
@queue.push(WAKEUP) if @thread
|
40
|
-
end
|
41
|
-
|
42
|
-
def wait
|
44
|
+
@queue.push([STOP, object_id]) if @thread
|
43
45
|
@thread.join if @thread
|
44
46
|
@dispatcher.cleanup
|
45
47
|
end
|
46
48
|
|
47
|
-
|
49
|
+
private
|
48
50
|
|
49
|
-
def
|
50
|
-
payload
|
51
|
-
|
51
|
+
def stop_payload?(payload)
|
52
|
+
payload.is_a?(Array) && payload.first == STOP
|
53
|
+
end
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
def should_stop?(payload)
|
56
|
+
payload.last == object_id
|
57
|
+
end
|
58
|
+
|
59
|
+
def dispatch(payload)
|
60
|
+
@dispatch_count += 1
|
61
|
+
@dispatcher.dispatch(payload)
|
62
|
+
rescue StandardError => e
|
63
|
+
log_error(e)
|
64
|
+
reflect(:error, e)
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
data/lib/rpush/daemon/feeder.rb
CHANGED
@@ -37,7 +37,7 @@ module Rpush
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.enqueue_notifications
|
40
|
-
batch_size = Rpush.config.batch_size - Rpush::Daemon::AppRunner.
|
40
|
+
batch_size = Rpush.config.batch_size - Rpush::Daemon::AppRunner.total_queued
|
41
41
|
return if batch_size <= 0
|
42
42
|
notifications = Rpush::Daemon.store.deliverable_notifications(batch_size)
|
43
43
|
Rpush::Daemon::AppRunner.enqueue(notifications)
|
@@ -6,9 +6,9 @@ module Rpush
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.proc_title
|
9
|
-
total_dispatchers = AppRunner.
|
9
|
+
total_dispatchers = AppRunner.total_dispatchers
|
10
10
|
dispatchers_str = total_dispatchers == 1 ? 'dispatcher' : 'dispatchers'
|
11
|
-
total_queued = AppRunner.
|
11
|
+
total_queued = AppRunner.total_queued
|
12
12
|
format("rpush | %s | %d queued | %d %s", Rpush.config.environment, total_queued, total_dispatchers, dispatchers_str)
|
13
13
|
end
|
14
14
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
class PGError < StandardError; end unless defined?(PGError)
|
2
|
+
module PG
|
3
|
+
class Error < StandardError; end unless defined?(::PG::Error)
|
4
|
+
end
|
2
5
|
class Mysql; class Error < StandardError; end; end unless defined?(Mysql)
|
3
6
|
module Mysql2; class Error < StandardError; end; end unless defined?(Mysql2)
|
4
7
|
module ActiveRecord
|
@@ -17,8 +20,9 @@ module Rpush
|
|
17
20
|
module Store
|
18
21
|
class ActiveRecord
|
19
22
|
module Reconnectable
|
20
|
-
ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError,
|
21
|
-
Mysql2::Error, ::ActiveRecord::JDBCError,
|
23
|
+
ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError, PG::Error,
|
24
|
+
Mysql::Error, Mysql2::Error, ::ActiveRecord::JDBCError,
|
25
|
+
SQLite3::Exception]
|
22
26
|
|
23
27
|
def with_database_reconnect_and_retry
|
24
28
|
::ActiveRecord::Base.connection_pool.with_connection do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
module StringHelpers
|
4
|
+
def pluralize(count, singular, plural = nil)
|
5
|
+
if count == 1 || count =~ /^1(\.0+)?$/
|
6
|
+
word = singular
|
7
|
+
else
|
8
|
+
word = plural || singular.pluralize
|
9
|
+
end
|
10
|
+
|
11
|
+
"#{count || 0} #{word}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
class Synchronizer
|
4
|
+
extend Loggable
|
5
|
+
extend StringHelpers
|
6
|
+
|
7
|
+
def self.sync
|
8
|
+
apps = Rpush::Daemon.store.all_apps
|
9
|
+
apps.each { |app| sync_app(app) }
|
10
|
+
removed = AppRunner.app_ids - apps.map(&:id)
|
11
|
+
removed.each { |app_id| AppRunner.stop_app(app_id) }
|
12
|
+
|
13
|
+
ProcTitle.update
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.sync_app(app)
|
17
|
+
unless AppRunner.app_running?(app)
|
18
|
+
AppRunner.start_app(app)
|
19
|
+
log_info("[#{app.name}] Started, #{pluralize(app.connections, 'dispatcher')}.")
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
sync_dispatcher_count(app)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.sync_dispatcher_count(app)
|
27
|
+
num_dispatchers = AppRunner.num_dispatchers_for_app(app)
|
28
|
+
diff = num_dispatchers - app.connections
|
29
|
+
return if diff == 0
|
30
|
+
|
31
|
+
if diff > 0
|
32
|
+
AppRunner.decrement_dispatchers(app, diff)
|
33
|
+
start_stop_str = "Stopped"
|
34
|
+
else
|
35
|
+
AppRunner.increment_dispatchers(app, diff.abs)
|
36
|
+
start_stop_str = "Started"
|
37
|
+
end
|
38
|
+
|
39
|
+
num_dispatchers = AppRunner.num_dispatchers_for_app(app)
|
40
|
+
log_info("[#{app.name}] #{start_stop_str} #{pluralize(diff.abs, 'dispatcher')}. #{num_dispatchers} running.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/rpush/embed.rb
CHANGED
data/lib/rpush/push.rb
CHANGED
data/lib/rpush/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'functional_spec_helper'
|
2
|
+
|
3
|
+
describe 'Synchronization' do
|
4
|
+
let(:timeout) { 10 }
|
5
|
+
let(:app) { Rpush::Gcm::App.new }
|
6
|
+
|
7
|
+
def wait_for_num_dispatchers(num)
|
8
|
+
Timeout.timeout(timeout) do
|
9
|
+
until Rpush::Daemon::AppRunner.num_dispatchers_for_app(app) == num
|
10
|
+
sleep 0.1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
app.name = 'test'
|
17
|
+
app.auth_key = 'abc123'
|
18
|
+
app.connections = 2
|
19
|
+
app.save!
|
20
|
+
|
21
|
+
Rpush.embed
|
22
|
+
wait_for_num_dispatchers(app.connections)
|
23
|
+
end
|
24
|
+
|
25
|
+
after { Timeout.timeout(timeout) { Rpush.shutdown } }
|
26
|
+
|
27
|
+
it 'increments the number of dispatchers' do
|
28
|
+
app.connections += 1
|
29
|
+
app.save!
|
30
|
+
Rpush.sync
|
31
|
+
wait_for_num_dispatchers(app.connections)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'decrements the number of dispatchers' do
|
35
|
+
app.connections -= 1
|
36
|
+
app.save!
|
37
|
+
Rpush.sync
|
38
|
+
wait_for_num_dispatchers(app.connections)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'stops a deleted app' do
|
42
|
+
app.destroy
|
43
|
+
Rpush.sync
|
44
|
+
Rpush::Daemon::AppRunner.app_running?(app).should be_false
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
ENV['RAILS_ENV'] = 'test'
|
2
|
+
client = (ENV['CLIENT'] || :active_record).to_sym
|
2
3
|
|
3
|
-
require 'bundler'
|
4
|
+
require 'bundler/setup'
|
4
5
|
Bundler.require(:default)
|
5
|
-
client = (ENV['CLIENT'] || :active_record).to_sym
|
6
6
|
|
7
7
|
unless ENV['TRAVIS'] && ENV['QUALITY'] == 'false'
|
8
8
|
begin
|
@@ -156,7 +156,7 @@ describe Rpush::Client::ActiveRecord::Apns::Notification, 'to_binary' do
|
|
156
156
|
notification.badge = nil
|
157
157
|
notification.sound = nil
|
158
158
|
notification.content_available = true
|
159
|
-
bytes = notification.to_binary.bytes[-4..-1]
|
159
|
+
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
160
160
|
bytes.first.should eq 5 # priority item ID
|
161
161
|
bytes.last.should eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_CONSERVE_POWER
|
162
162
|
end
|
@@ -166,7 +166,7 @@ describe Rpush::Client::ActiveRecord::Apns::Notification, 'to_binary' do
|
|
166
166
|
notification.badge = nil
|
167
167
|
notification.sound = nil
|
168
168
|
notification.content_available = true
|
169
|
-
bytes = notification.to_binary.bytes[-4..-1]
|
169
|
+
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
170
170
|
bytes.first.should eq 5 # priority item ID
|
171
171
|
bytes.last.should eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_IMMEDIATE
|
172
172
|
end
|
@@ -134,7 +134,7 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
134
134
|
describe 'a 429 (Too Many Request) response' do
|
135
135
|
let(:http) { double(shutdown: nil) }
|
136
136
|
let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: %w(abc xyz), deliver_after: Time.now, collapse_key: 'sync', data: { 'message' => 'test' }) }
|
137
|
-
let(:
|
137
|
+
let(:rate_limited_response) { double(code: 429, header: { 'retry-after' => 3600 }) }
|
138
138
|
|
139
139
|
it 'should retry the entire notification respecting the Retry-After header if none sent out yet' do
|
140
140
|
response.stub(code: 429, header: { 'retry-after' => 3600 })
|
@@ -167,7 +167,7 @@ describe Rpush::Daemon::Adm::Delivery do
|
|
167
167
|
|
168
168
|
# first request to deliver message that returns too many request response
|
169
169
|
adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'xyz'))
|
170
|
-
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(
|
170
|
+
http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(rate_limited_response)
|
171
171
|
|
172
172
|
store.should_receive(:update_notification).with do |notif|
|
173
173
|
notif.registration_ids.include?('abc').should be_true
|
@@ -31,104 +31,49 @@ module Rpush
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe Rpush::Daemon::AppRunner, 'stop' do
|
35
|
-
let(:runner) { double }
|
36
|
-
before { Rpush::Daemon::AppRunner.runners['app'] = runner }
|
37
|
-
after { Rpush::Daemon::AppRunner.runners.clear }
|
38
|
-
|
39
|
-
it 'stops all runners' do
|
40
|
-
runner.should_receive(:stop)
|
41
|
-
Rpush::Daemon::AppRunner.stop
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
34
|
describe Rpush::Daemon::AppRunner, 'enqueue' do
|
46
|
-
let(:
|
47
|
-
let(:
|
48
|
-
let(:
|
35
|
+
let(:app) { double(id: 1) }
|
36
|
+
let(:notification) { double(app_id: 1) }
|
37
|
+
let(:runner) { double(Rpush::Daemon::AppRunner, enqueue: nil, start: nil, stop: nil) }
|
49
38
|
let(:logger) { double(Rpush::Logger, error: nil, info: nil) }
|
50
39
|
|
51
40
|
before do
|
52
41
|
Rpush.stub(logger: logger)
|
53
42
|
Rpush::Daemon::ProcTitle.stub(:update)
|
54
|
-
Rpush::Daemon::AppRunner.
|
55
|
-
Rpush::Daemon::AppRunner.
|
43
|
+
Rpush::Daemon::AppRunner.stub(new: runner)
|
44
|
+
Rpush::Daemon::AppRunner.start_app(app)
|
56
45
|
end
|
57
46
|
|
58
|
-
after { Rpush::Daemon::AppRunner.
|
47
|
+
after { Rpush::Daemon::AppRunner.stop }
|
59
48
|
|
60
|
-
it 'enqueues notifications on
|
61
|
-
runner.should_receive(:enqueue).with([
|
62
|
-
|
63
|
-
Rpush::Daemon::AppRunner.enqueue([notification1, notification2])
|
49
|
+
it 'enqueues notifications on the runner' do
|
50
|
+
runner.should_receive(:enqueue).with([notification])
|
51
|
+
Rpush::Daemon::AppRunner.enqueue([notification])
|
64
52
|
end
|
65
53
|
|
66
|
-
it '
|
67
|
-
Rpush::Daemon::AppRunner.runners[3].should be_nil
|
54
|
+
it 'starts the app if a runner does not exist' do
|
68
55
|
notification = double(app_id: 3)
|
69
|
-
|
70
|
-
Rpush::Daemon.store = double(app:
|
56
|
+
new_app = double(Rpush::App, id: 3)
|
57
|
+
Rpush::Daemon.store = double(app: new_app)
|
71
58
|
Rpush::Daemon::AppRunner.enqueue([notification])
|
72
|
-
Rpush::Daemon::AppRunner.
|
59
|
+
Rpush::Daemon::AppRunner.app_running?(new_app).should be_true
|
73
60
|
end
|
74
61
|
end
|
75
62
|
|
76
|
-
describe Rpush::Daemon::AppRunner, '
|
77
|
-
let(:app) { double(
|
78
|
-
let(:
|
79
|
-
let(:
|
80
|
-
let(:logger) { double(Rpush::Logger, error: nil, warn: nil) }
|
81
|
-
let(:queue) { Queue.new }
|
82
|
-
let(:store) { double(all_apps: [app]) }
|
63
|
+
describe Rpush::Daemon::AppRunner, 'start_app' do
|
64
|
+
let(:app) { double(id: 1, name: 'test') }
|
65
|
+
let(:runner) { double(Rpush::Daemon::AppRunner, enqueue: nil, start: nil, stop: nil) }
|
66
|
+
let(:logger) { double(Rpush::Logger, error: nil, info: nil) }
|
83
67
|
|
84
68
|
before do
|
85
|
-
app.stub(id: 1)
|
86
|
-
new_app.stub(id: 2)
|
87
|
-
Queue.stub(new: queue)
|
88
|
-
Rpush::Daemon::AppRunner.runners[app.id] = runner
|
89
69
|
Rpush.stub(logger: logger)
|
90
|
-
Rpush::Daemon.stub(store: store)
|
91
|
-
Rpush::Daemon::ProcTitle.stub(:update)
|
92
|
-
end
|
93
|
-
|
94
|
-
after { Rpush::Daemon::AppRunner.runners.clear }
|
95
|
-
|
96
|
-
it 'instructs existing runners to sync' do
|
97
|
-
runner.should_receive(:sync).with(app)
|
98
|
-
Rpush::Daemon::AppRunner.sync
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'starts a runner for a new app' do
|
102
|
-
store.stub(all_apps: [app, new_app])
|
103
|
-
new_runner = double
|
104
|
-
Rpush::Daemon::AppRunner.should_receive(:new).with(new_app).and_return(new_runner)
|
105
|
-
new_runner.should_receive(:start)
|
106
|
-
Rpush::Daemon::AppRunner.sync
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'deletes old runners' do
|
110
|
-
store.stub(all_apps: [])
|
111
|
-
runner.should_receive(:stop)
|
112
|
-
Rpush::Daemon::AppRunner.sync
|
113
70
|
end
|
114
71
|
|
115
72
|
it 'logs an error if the runner could not be started' do
|
116
|
-
|
117
|
-
|
118
|
-
Rpush::Daemon::AppRunner.should_receive(:new).with(new_app).and_return(new_runner)
|
119
|
-
new_runner.stub(:start).and_raise(StandardError)
|
73
|
+
Rpush::Daemon::AppRunner.should_receive(:new).with(app).and_return(runner)
|
74
|
+
runner.stub(:start).and_raise(StandardError)
|
120
75
|
Rpush.logger.should_receive(:error)
|
121
|
-
Rpush::Daemon::AppRunner.
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'reflects errors if the runner could not be started' do
|
125
|
-
store.stub(all_apps: [app, new_app])
|
126
|
-
new_runner = double
|
127
|
-
Rpush::Daemon::AppRunner.should_receive(:new).with(new_app).and_return(new_runner)
|
128
|
-
e = StandardError.new
|
129
|
-
new_runner.stub(:start).and_raise(e)
|
130
|
-
Rpush::Daemon::AppRunner.should_receive(:reflect).with(:error, e)
|
131
|
-
Rpush::Daemon::AppRunner.sync
|
76
|
+
Rpush::Daemon::AppRunner.start_app(app)
|
132
77
|
end
|
133
78
|
end
|
134
79
|
|
@@ -137,15 +82,15 @@ describe Rpush::Daemon::AppRunner, 'debug' do
|
|
137
82
|
environment: 'development', certificate: TEST_CERT, service_name: 'app_runner_spec_service')
|
138
83
|
end
|
139
84
|
let(:logger) { double(Rpush::Logger, info: nil) }
|
140
|
-
let(:store) { double(all_apps: [app]) }
|
85
|
+
let(:store) { double(all_apps: [app], release_connection: nil) }
|
141
86
|
|
142
87
|
before do
|
143
88
|
Rpush::Daemon.stub(config: {}, store: store)
|
144
89
|
Rpush.stub(logger: logger)
|
145
|
-
Rpush::Daemon::AppRunner.
|
90
|
+
Rpush::Daemon::AppRunner.start_app(app)
|
146
91
|
end
|
147
92
|
|
148
|
-
after { Rpush::Daemon::AppRunner.
|
93
|
+
after { Rpush::Daemon::AppRunner.stop_app(app.id) }
|
149
94
|
|
150
95
|
it 'prints debug app states to the log' do
|
151
96
|
Rpush.logger.should_receive(:info).with(kind_of(String))
|
@@ -161,18 +106,16 @@ describe Rpush::Daemon::AppRunner do
|
|
161
106
|
let(:runner) { Rpush::Daemon::AppRunner.new(app) }
|
162
107
|
let(:logger) { double(Rpush::Logger, info: nil) }
|
163
108
|
let(:queue) { Queue.new }
|
164
|
-
let(:
|
165
|
-
let(:
|
166
|
-
start: nil, stop: nil)
|
167
|
-
end
|
109
|
+
let(:service_loop) { double(Rpush::Daemon::AppRunnerSpecService::ServiceLoop, start: nil, stop: nil) }
|
110
|
+
let(:dispatcher_loop) { double(Rpush::Daemon::DispatcherLoop, stop: nil, start: nil) }
|
168
111
|
let(:store) { double(Rpush::Daemon::Store::ActiveRecord, release_connection: nil) }
|
169
112
|
|
170
113
|
before do
|
114
|
+
Rpush::Daemon::DispatcherLoop.stub(new: dispatcher_loop)
|
171
115
|
Rpush::Daemon.stub(store: store)
|
172
116
|
Rpush::Daemon::AppRunnerSpecService::ServiceLoop.stub(new: service_loop)
|
173
117
|
Queue.stub(new: queue)
|
174
118
|
Rpush.stub(logger: logger)
|
175
|
-
Rpush::Daemon::DispatcherLoopCollection.stub(new: dispatcher_loop_collection)
|
176
119
|
end
|
177
120
|
|
178
121
|
describe 'start' do
|
@@ -182,6 +125,11 @@ describe Rpush::Daemon::AppRunner do
|
|
182
125
|
runner.num_dispatcher_loops.should eq 2
|
183
126
|
end
|
184
127
|
|
128
|
+
it 'starts the dispatcher loop' do
|
129
|
+
dispatcher_loop.should_receive(:start)
|
130
|
+
runner.start
|
131
|
+
end
|
132
|
+
|
185
133
|
it 'starts the loops' do
|
186
134
|
service_loop.should_receive(:start)
|
187
135
|
runner.start
|
@@ -209,7 +157,7 @@ describe Rpush::Daemon::AppRunner do
|
|
209
157
|
before { runner.start }
|
210
158
|
|
211
159
|
it 'stops the delivery dispatchers' do
|
212
|
-
|
160
|
+
dispatcher_loop.should_receive(:stop)
|
213
161
|
runner.stop
|
214
162
|
end
|
215
163
|
|
@@ -218,18 +166,4 @@ describe Rpush::Daemon::AppRunner do
|
|
218
166
|
runner.stop
|
219
167
|
end
|
220
168
|
end
|
221
|
-
|
222
|
-
describe 'sync' do
|
223
|
-
before { runner.start }
|
224
|
-
|
225
|
-
it 'reduces the number of dispatchers if needed' do
|
226
|
-
app.stub(connections: 0)
|
227
|
-
expect { runner.sync(app) }.to change(runner, :num_dispatcher_loops).to(0)
|
228
|
-
end
|
229
|
-
|
230
|
-
it 'increases the number of dispatchers if needed' do
|
231
|
-
app.stub(connections: 2)
|
232
|
-
expect { runner.sync(app) }.to change(runner, :num_dispatcher_loops).to(2)
|
233
|
-
end
|
234
|
-
end
|
235
169
|
end
|
@@ -4,8 +4,6 @@ describe Rpush::Daemon::DispatcherLoop do
|
|
4
4
|
def run_dispatcher_loop
|
5
5
|
dispatcher_loop.start
|
6
6
|
dispatcher_loop.stop
|
7
|
-
dispatcher_loop.wakeup
|
8
|
-
dispatcher_loop.wait
|
9
7
|
end
|
10
8
|
|
11
9
|
let(:notification) { double }
|
@@ -37,20 +35,9 @@ describe Rpush::Daemon::DispatcherLoop do
|
|
37
35
|
run_dispatcher_loop
|
38
36
|
end
|
39
37
|
|
40
|
-
it 'instructs the queue to wakeup the thread when told to stop' do
|
41
|
-
queue.should_receive(:push).with(Rpush::Daemon::DispatcherLoop::WAKEUP).and_call_original
|
42
|
-
run_dispatcher_loop
|
43
|
-
end
|
44
|
-
|
45
38
|
describe 'stop' do
|
46
39
|
before do
|
47
40
|
queue.clear
|
48
|
-
queue.push(Rpush::Daemon::DispatcherLoop::WAKEUP)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'does not attempt to dispatch when a WAKEUP is dequeued' do
|
52
|
-
dispatcher.should_not_receive(:dispatch)
|
53
|
-
run_dispatcher_loop
|
54
41
|
end
|
55
42
|
|
56
43
|
it 'instructs the dispatcher to cleanup' do
|
@@ -33,14 +33,14 @@ describe Rpush::Daemon::Feeder do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'does not load more notifications if the total queue size is equal to the batch size' do
|
36
|
-
Rpush::Daemon::AppRunner.stub(
|
36
|
+
Rpush::Daemon::AppRunner.stub(total_queued: Rpush.config.batch_size)
|
37
37
|
Rpush::Daemon.store.should_not_receive(:deliverable_notifications)
|
38
38
|
start_and_stop
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'limits the batch size if some runners are still processing notifications' do
|
42
42
|
Rpush.config.stub(batch_size: 10)
|
43
|
-
Rpush::Daemon::AppRunner.stub(
|
43
|
+
Rpush::Daemon::AppRunner.stub(total_queued: 6)
|
44
44
|
Rpush::Daemon.store.should_receive(:deliverable_notifications).with(4)
|
45
45
|
start_and_stop
|
46
46
|
end
|
@@ -42,13 +42,13 @@ describe Rpush::Daemon::SignalHandler do
|
|
42
42
|
|
43
43
|
describe 'HUP' do
|
44
44
|
before do
|
45
|
-
Rpush::Daemon::
|
45
|
+
Rpush::Daemon::Synchronizer.stub(:sync)
|
46
46
|
Rpush::Daemon::Feeder.stub(:wakeup)
|
47
47
|
end
|
48
48
|
|
49
|
-
it 'syncs
|
49
|
+
it 'syncs' do
|
50
50
|
with_handler_start_stop do
|
51
|
-
Rpush::Daemon::
|
51
|
+
Rpush::Daemon::Synchronizer.should_receive(:sync)
|
52
52
|
signal_handler('HUP')
|
53
53
|
end
|
54
54
|
end
|
data/spec/unit/daemon_spec.rb
CHANGED
@@ -11,7 +11,8 @@ describe Rpush::Daemon, "when starting" do
|
|
11
11
|
before do
|
12
12
|
Rpush.stub(logger: logger)
|
13
13
|
Rpush::Daemon::Feeder.stub(:start)
|
14
|
-
Rpush::Daemon::
|
14
|
+
Rpush::Daemon::Synchronizer.stub(sync: nil)
|
15
|
+
Rpush::Daemon::AppRunner.stub(stop: nil)
|
15
16
|
Rpush::Daemon.stub(exit: nil, puts: nil)
|
16
17
|
Rpush::Daemon::SignalHandler.stub(start: nil, stop: nil, handle_shutdown_signal: nil)
|
17
18
|
Process.stub(:daemon)
|
@@ -87,7 +88,7 @@ describe Rpush::Daemon, "when starting" do
|
|
87
88
|
end
|
88
89
|
|
89
90
|
it "syncs apps" do
|
90
|
-
Rpush::Daemon::
|
91
|
+
Rpush::Daemon::Synchronizer.should_receive(:sync)
|
91
92
|
Rpush::Daemon.start
|
92
93
|
end
|
93
94
|
|
data/spec/unit/embed_spec.rb
CHANGED
@@ -36,8 +36,8 @@ end
|
|
36
36
|
describe Rpush, 'sync' do
|
37
37
|
before { Rpush.config.embedded = true }
|
38
38
|
|
39
|
-
it 'syncs
|
40
|
-
Rpush::Daemon::
|
39
|
+
it 'syncs' do
|
40
|
+
Rpush::Daemon::Synchronizer.should_receive(:sync)
|
41
41
|
Rpush.sync
|
42
42
|
end
|
43
43
|
end
|
data/spec/unit/logger_spec.rb
CHANGED
@@ -70,11 +70,13 @@ describe Rpush::Logger do
|
|
70
70
|
logger.info("hi mom")
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
73
|
+
unless Rpush.jruby? # These tests do not work on JRuby.
|
74
|
+
it "should not print out the msg if not running in the foreground" do
|
75
|
+
Rpush.config.foreground = false
|
76
|
+
logger = Rpush::Logger.new
|
77
|
+
STDOUT.should_not_receive(:puts).with(/hi mom/)
|
78
|
+
logger.info("hi mom")
|
79
|
+
end
|
78
80
|
end
|
79
81
|
|
80
82
|
it "should prefix log lines with the current time" do
|
data/spec/unit/push_spec.rb
CHANGED
@@ -2,7 +2,8 @@ require 'unit_spec_helper'
|
|
2
2
|
|
3
3
|
describe Rpush, 'push' do
|
4
4
|
before do
|
5
|
-
Rpush::Daemon::
|
5
|
+
Rpush::Daemon::Synchronizer.stub(sync: nil)
|
6
|
+
Rpush::Daemon::AppRunner.stub(wait: nil)
|
6
7
|
Rpush::Daemon::Feeder.stub(start: nil)
|
7
8
|
end
|
8
9
|
|
@@ -16,8 +17,8 @@ describe Rpush, 'push' do
|
|
16
17
|
Rpush.push
|
17
18
|
end
|
18
19
|
|
19
|
-
it 'syncs
|
20
|
-
Rpush::Daemon::
|
20
|
+
it 'syncs' do
|
21
|
+
Rpush::Daemon::Synchronizer.should_receive(:sync)
|
21
22
|
Rpush.push
|
22
23
|
end
|
23
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Leitch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -136,7 +136,6 @@ files:
|
|
136
136
|
- lib/rpush/daemon/dispatcher/http.rb
|
137
137
|
- lib/rpush/daemon/dispatcher/tcp.rb
|
138
138
|
- lib/rpush/daemon/dispatcher_loop.rb
|
139
|
-
- lib/rpush/daemon/dispatcher_loop_collection.rb
|
140
139
|
- lib/rpush/daemon/errors.rb
|
141
140
|
- lib/rpush/daemon/feeder.rb
|
142
141
|
- lib/rpush/daemon/gcm.rb
|
@@ -155,8 +154,9 @@ files:
|
|
155
154
|
- lib/rpush/daemon/store/active_record/reconnectable.rb
|
156
155
|
- lib/rpush/daemon/store/interface.rb
|
157
156
|
- lib/rpush/daemon/store/redis.rb
|
157
|
+
- lib/rpush/daemon/string_helpers.rb
|
158
|
+
- lib/rpush/daemon/synchronizer.rb
|
158
159
|
- lib/rpush/daemon/tcp_connection.rb
|
159
|
-
- lib/rpush/daemon/too_many_requests_error.rb
|
160
160
|
- lib/rpush/daemon/wpns.rb
|
161
161
|
- lib/rpush/daemon/wpns/delivery.rb
|
162
162
|
- lib/rpush/deprecatable.rb
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- spec/functional/gcm_spec.rb
|
177
177
|
- spec/functional/new_app_spec.rb
|
178
178
|
- spec/functional/retry_spec.rb
|
179
|
+
- spec/functional/synchronization_spec.rb
|
179
180
|
- spec/functional/wpns_spec.rb
|
180
181
|
- spec/functional_spec_helper.rb
|
181
182
|
- spec/integration/rpush_spec.rb
|
@@ -212,7 +213,6 @@ files:
|
|
212
213
|
- spec/unit/daemon/delivery_spec.rb
|
213
214
|
- spec/unit/daemon/dispatcher/http_spec.rb
|
214
215
|
- spec/unit/daemon/dispatcher/tcp_spec.rb
|
215
|
-
- spec/unit/daemon/dispatcher_loop_collection_spec.rb
|
216
216
|
- spec/unit/daemon/dispatcher_loop_spec.rb
|
217
217
|
- spec/unit/daemon/feeder_spec.rb
|
218
218
|
- spec/unit/daemon/gcm/delivery_spec.rb
|
@@ -223,7 +223,6 @@ files:
|
|
223
223
|
- spec/unit/daemon/store/active_record/reconnectable_spec.rb
|
224
224
|
- spec/unit/daemon/store/active_record_spec.rb
|
225
225
|
- spec/unit/daemon/tcp_connection_spec.rb
|
226
|
-
- spec/unit/daemon/too_many_requests_error_spec.rb
|
227
226
|
- spec/unit/daemon/wpns/delivery_spec.rb
|
228
227
|
- spec/unit/daemon_spec.rb
|
229
228
|
- spec/unit/deprecatable_spec.rb
|
@@ -267,6 +266,7 @@ test_files:
|
|
267
266
|
- spec/functional/gcm_spec.rb
|
268
267
|
- spec/functional/new_app_spec.rb
|
269
268
|
- spec/functional/retry_spec.rb
|
269
|
+
- spec/functional/synchronization_spec.rb
|
270
270
|
- spec/functional/wpns_spec.rb
|
271
271
|
- spec/functional_spec_helper.rb
|
272
272
|
- spec/integration/rpush_spec.rb
|
@@ -303,7 +303,6 @@ test_files:
|
|
303
303
|
- spec/unit/daemon/delivery_spec.rb
|
304
304
|
- spec/unit/daemon/dispatcher/http_spec.rb
|
305
305
|
- spec/unit/daemon/dispatcher/tcp_spec.rb
|
306
|
-
- spec/unit/daemon/dispatcher_loop_collection_spec.rb
|
307
306
|
- spec/unit/daemon/dispatcher_loop_spec.rb
|
308
307
|
- spec/unit/daemon/feeder_spec.rb
|
309
308
|
- spec/unit/daemon/gcm/delivery_spec.rb
|
@@ -314,7 +313,6 @@ test_files:
|
|
314
313
|
- spec/unit/daemon/store/active_record/reconnectable_spec.rb
|
315
314
|
- spec/unit/daemon/store/active_record_spec.rb
|
316
315
|
- spec/unit/daemon/tcp_connection_spec.rb
|
317
|
-
- spec/unit/daemon/too_many_requests_error_spec.rb
|
318
316
|
- spec/unit/daemon/wpns/delivery_spec.rb
|
319
317
|
- spec/unit/daemon_spec.rb
|
320
318
|
- spec/unit/deprecatable_spec.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Rpush
|
2
|
-
module Daemon
|
3
|
-
class DispatcherLoopCollection
|
4
|
-
attr_reader :loops
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@loops = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def push(dispatcher_loop)
|
11
|
-
@loops << dispatcher_loop
|
12
|
-
end
|
13
|
-
|
14
|
-
def pop
|
15
|
-
dispatcher_loop = @loops.pop
|
16
|
-
dispatcher_loop.stop
|
17
|
-
dispatcher_loop.wakeup
|
18
|
-
@loops.map(&:wakeup)
|
19
|
-
dispatcher_loop.wait
|
20
|
-
end
|
21
|
-
|
22
|
-
def size
|
23
|
-
@loops.size
|
24
|
-
end
|
25
|
-
|
26
|
-
def stop
|
27
|
-
@loops.map(&:stop)
|
28
|
-
@loops.map(&:wakeup)
|
29
|
-
@loops.map(&:wait)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Rpush
|
2
|
-
class TooManyRequestsError < StandardError
|
3
|
-
attr_reader :code, :description, :response
|
4
|
-
|
5
|
-
def initialize(code, notification_id, description, response)
|
6
|
-
@code = code
|
7
|
-
@notification_id = notification_id
|
8
|
-
@description = description
|
9
|
-
@response = response
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
message
|
14
|
-
end
|
15
|
-
|
16
|
-
def message
|
17
|
-
"Too many requests for #{@notification_id}, received error #{@code} (#{@description}) - retry after #{@response.header['retry-after']}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
|
3
|
-
describe Rpush::Daemon::DispatcherLoopCollection do
|
4
|
-
let(:dispatcher_loop) { double.as_null_object }
|
5
|
-
let(:collection) { Rpush::Daemon::DispatcherLoopCollection.new }
|
6
|
-
|
7
|
-
it 'returns the size of the collection' do
|
8
|
-
collection.push(dispatcher_loop)
|
9
|
-
collection.size.should eq 1
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'pops a dispatcher loop from the collection' do
|
13
|
-
collection.push(dispatcher_loop)
|
14
|
-
dispatcher_loop.should_receive(:stop)
|
15
|
-
dispatcher_loop.should_receive(:wakeup)
|
16
|
-
dispatcher_loop.should_receive(:wait)
|
17
|
-
collection.pop
|
18
|
-
collection.size.should eq 0
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'wakes up all dispatcher loops when popping a single dispatcher_loop' do
|
22
|
-
collection.push(dispatcher_loop)
|
23
|
-
dispatcher_loop2 = double.as_null_object
|
24
|
-
collection.push(dispatcher_loop2)
|
25
|
-
dispatcher_loop.should_receive(:wakeup)
|
26
|
-
dispatcher_loop2.should_receive(:wakeup)
|
27
|
-
collection.pop
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'stops all dispatcher detetcloops' do
|
31
|
-
collection.push(dispatcher_loop)
|
32
|
-
dispatcher_loop.should_receive(:stop)
|
33
|
-
dispatcher_loop.should_receive(:wakeup)
|
34
|
-
dispatcher_loop.should_receive(:wait)
|
35
|
-
collection.stop
|
36
|
-
end
|
37
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require "unit_spec_helper"
|
2
|
-
|
3
|
-
describe Rpush::TooManyRequestsError do
|
4
|
-
let(:response) { double(code: 429, header: { 'retry-after' => 3600 }) }
|
5
|
-
let(:error) { Rpush::TooManyRequestsError.new(429, 12, "Too Many Requests", response) }
|
6
|
-
|
7
|
-
it "returns an informative message" do
|
8
|
-
error.to_s.should eq "Too many requests for 12, received error 429 (Too Many Requests) - retry after 3600"
|
9
|
-
end
|
10
|
-
|
11
|
-
it "returns the error code" do
|
12
|
-
error.code.should eq 429
|
13
|
-
end
|
14
|
-
end
|