ably-rest 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/SPEC.md +1380 -631
- data/ably-rest.gemspec +11 -5
- data/lib/submodules/ably-ruby/.travis.yml +1 -1
- data/lib/submodules/ably-ruby/CHANGELOG.md +42 -48
- data/lib/submodules/ably-ruby/ably.gemspec +7 -1
- data/lib/submodules/ably-ruby/lib/ably.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +155 -47
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +2 -3
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +54 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +14 -4
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +13 -7
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +3 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +1 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +15 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +10 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +62 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +58 -54
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +18 -5
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +32 -14
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +251 -11
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +12 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +316 -24
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +93 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +177 -86
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +284 -60
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +45 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +4 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +181 -49
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +13 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +222 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +132 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -28
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +7 -7
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +10 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +41 -17
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -0
- data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +16 -0
- data/lib/submodules/ably-ruby/spec/unit/models/connection_details_spec.rb +60 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +45 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +6 -5
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +5 -1
- metadata +57 -13
@@ -53,7 +53,7 @@ describe Ably::Realtime::Client, :event_machine do
|
|
53
53
|
connection.on(:connected) do
|
54
54
|
expect(auth_params[:access_token]).to_not be_nil
|
55
55
|
expect(auth_params[:key]).to be_nil
|
56
|
-
expect(subject.auth.current_token_details).to
|
56
|
+
expect(subject.auth.current_token_details).to be_a(Ably::Models::TokenDetails)
|
57
57
|
stop_reactor
|
58
58
|
end
|
59
59
|
end
|
@@ -113,6 +113,98 @@ describe Ably::Realtime::Client, :event_machine do
|
|
113
113
|
stop_reactor
|
114
114
|
end
|
115
115
|
end
|
116
|
+
|
117
|
+
context 'when the returned token has a client_id' do
|
118
|
+
it "sets Auth#client_id to the new token's client_id immediately when connecting" do
|
119
|
+
subject.auth.authorise do
|
120
|
+
expect(subject.connection).to be_connecting
|
121
|
+
expect(subject.auth.client_id).to eql(client_id)
|
122
|
+
stop_reactor
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "sets Client#client_id to the new token's client_id immediately when connecting" do
|
127
|
+
subject.auth.authorise do
|
128
|
+
expect(subject.connection).to be_connecting
|
129
|
+
expect(subject.client_id).to eql(client_id)
|
130
|
+
stop_reactor
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with a wildcard client_id token' do
|
136
|
+
subject { auto_close Ably::Realtime::Client.new(client_options) }
|
137
|
+
let(:client_options) { default_options.merge(auth_callback: Proc.new { auth_token_object }, client_id: client_id) }
|
138
|
+
let(:rest_auth_client) { Ably::Rest::Client.new(default_options.merge(key: api_key)) }
|
139
|
+
let(:auth_token_object) { rest_auth_client.auth.request_token(client_id: '*') }
|
140
|
+
|
141
|
+
context 'and an explicit client_id in ClientOptions' do
|
142
|
+
let(:client_id) { random_str }
|
143
|
+
|
144
|
+
it 'allows uses the explicit client_id in the connection' do
|
145
|
+
connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
146
|
+
if protocol_message.action == :connected
|
147
|
+
expect(protocol_message.connection_details.client_id).to eql(client_id)
|
148
|
+
@valid_client_id = true
|
149
|
+
end
|
150
|
+
end
|
151
|
+
subject.connect do
|
152
|
+
EM.add_timer(0.5) { stop_reactor if @valid_client_id }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'and client_id omitted in ClientOptions' do
|
158
|
+
let(:client_options) { default_options.merge(auth_callback: Proc.new { auth_token_object }) }
|
159
|
+
|
160
|
+
it 'uses the token provided clientId in the connection' do
|
161
|
+
connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
162
|
+
if protocol_message.action == :connected
|
163
|
+
expect(protocol_message.connection_details.client_id).to eql('*')
|
164
|
+
@valid_client_id = true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
subject.connect do
|
168
|
+
EM.add_timer(0.5) { stop_reactor if @valid_client_id }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'with an invalid wildcard "*" :client_id' do
|
176
|
+
it 'raises an exception' do
|
177
|
+
expect { Ably::Realtime::Client.new(client_options.merge(key: api_key, client_id: '*')) }.to raise_error ArgumentError
|
178
|
+
stop_reactor
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'realtime connection settings' do
|
184
|
+
context 'defaults' do
|
185
|
+
specify 'disconnected_retry_timeout is 15s' do
|
186
|
+
expect(subject.connection.defaults[:disconnected_retry_timeout]).to eql(15)
|
187
|
+
stop_reactor
|
188
|
+
end
|
189
|
+
|
190
|
+
specify 'suspended_retry_timeout is 30s' do
|
191
|
+
expect(subject.connection.defaults[:suspended_retry_timeout]).to eql(30)
|
192
|
+
stop_reactor
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'overriden in ClientOptions' do
|
197
|
+
let(:client_options) { default_options.merge(disconnected_retry_timeout: 1, suspended_retry_timeout: 2) }
|
198
|
+
|
199
|
+
specify 'disconnected_retry_timeout is updated' do
|
200
|
+
expect(subject.connection.defaults[:disconnected_retry_timeout]).to eql(1)
|
201
|
+
stop_reactor
|
202
|
+
end
|
203
|
+
|
204
|
+
specify 'suspended_retry_timeout is updated' do
|
205
|
+
expect(subject.connection.defaults[:suspended_retry_timeout]).to eql(2)
|
206
|
+
stop_reactor
|
207
|
+
end
|
116
208
|
end
|
117
209
|
end
|
118
210
|
end
|
@@ -53,19 +53,17 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
context 'automatic connection retry' do
|
56
|
-
let(:client_failure_options) { default_options.merge(log_level: :none) }
|
57
|
-
|
58
56
|
context 'with invalid WebSocket host' do
|
59
57
|
let(:retry_every_for_tests) { 0.2 }
|
60
58
|
let(:max_time_in_state_for_tests) { 0.6 }
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
let(:client_failure_options) do
|
61
|
+
default_options.merge(
|
62
|
+
log_level: :none,
|
63
|
+
disconnected_retry_timeout: retry_every_for_tests,
|
64
|
+
suspended_retry_timeout: retry_every_for_tests,
|
65
|
+
connection_state_ttl: max_time_in_state_for_tests
|
66
|
+
)
|
69
67
|
end
|
70
68
|
|
71
69
|
# retry immediately after failure, then one retry every :retry_every_for_tests
|
@@ -110,6 +108,27 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
110
108
|
end
|
111
109
|
end
|
112
110
|
|
111
|
+
context 'for the first time' do
|
112
|
+
let(:client_options) do
|
113
|
+
default_options.merge(realtime_host: 'non.existent.host', disconnected_retry_timeout: 2, log_level: :error)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'reattempts connection immediately and then waits disconnected_retry_timeout for a subsequent attempt' do
|
117
|
+
expect(connection.defaults[:disconnected_retry_timeout]).to eql(2)
|
118
|
+
connection.once(:disconnected) do
|
119
|
+
started_at = Time.now.to_f
|
120
|
+
connection.once(:disconnected) do
|
121
|
+
expect(Time.now.to_f - started_at).to be < 1
|
122
|
+
started_at = Time.now.to_f
|
123
|
+
connection.once(:disconnected) do
|
124
|
+
expect(Time.now.to_f - started_at).to be > 2
|
125
|
+
stop_reactor
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
113
132
|
describe '#close' do
|
114
133
|
it 'transitions connection state to :closed' do
|
115
134
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
@@ -130,25 +149,50 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
130
149
|
end
|
131
150
|
|
132
151
|
context 'when connection state is :suspended' do
|
133
|
-
it '
|
152
|
+
it 'stays in the suspended state after any number of reconnection attempts' do
|
134
153
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
135
154
|
|
136
155
|
connection.once(:suspended) do
|
137
156
|
count_state_changes && start_timer
|
138
157
|
|
139
|
-
|
140
|
-
expect(connection.state).to eq(:
|
158
|
+
EventMachine.add_timer((retry_every_for_tests + 0.1) * 10) do
|
159
|
+
expect(connection.state).to eq(:suspended)
|
141
160
|
|
142
|
-
expect(state_changes[:connecting]).to
|
143
|
-
expect(state_changes[:suspended]).to
|
161
|
+
expect(state_changes[:connecting]).to be >= 10
|
162
|
+
expect(state_changes[:suspended]).to be >= 10
|
144
163
|
expect(state_changes[:disconnected]).to eql(0)
|
145
164
|
|
146
|
-
expect(time_passed).to be > max_time_in_state_for_tests
|
147
165
|
stop_reactor
|
148
166
|
end
|
149
167
|
end
|
150
168
|
end
|
151
169
|
|
170
|
+
context 'for the first time' do
|
171
|
+
let(:client_options) do
|
172
|
+
default_options.merge(suspended_retry_timeout: 2, connection_state_ttl: 0, log_level: :error)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'waits suspended_retry_timeout before attempting to reconnect' do
|
176
|
+
expect(client.connection.defaults[:suspended_retry_timeout]).to eql(2)
|
177
|
+
connection.once(:connected) do
|
178
|
+
connection.transition_state_machine :suspended
|
179
|
+
allow(connection).to receive(:current_host).and_return('does.not.exist.com')
|
180
|
+
|
181
|
+
started_at = Time.now.to_f
|
182
|
+
connection.once(:connecting) do
|
183
|
+
expect(Time.now.to_f - started_at).to be > 1.75
|
184
|
+
started_at = Time.now.to_f
|
185
|
+
connection.once(:connecting) do
|
186
|
+
expect(Time.now.to_f - started_at).to be > 1.75
|
187
|
+
connection.once(:suspended) do
|
188
|
+
stop_reactor
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
152
196
|
describe '#close' do
|
153
197
|
it 'transitions connection state to :closed' do
|
154
198
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
@@ -172,6 +216,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
172
216
|
it 'will not transition state to :close and raises a InvalidStateChange exception' do
|
173
217
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
174
218
|
|
219
|
+
connection.once(:suspended) do
|
220
|
+
connection.transition_state_machine :failed
|
221
|
+
end
|
222
|
+
|
175
223
|
connection.once(:failed) do
|
176
224
|
expect(connection.state).to eq(:failed)
|
177
225
|
expect { connection.close }.to raise_error Ably::Exceptions::InvalidStateChange, /Unable to transition from failed => closing/
|
@@ -190,6 +238,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
190
238
|
expect(connection.error_reason.code).to eql(80000)
|
191
239
|
stop_reactor
|
192
240
|
end
|
241
|
+
|
242
|
+
connection.once(:suspended) do |connection_state_change|
|
243
|
+
connection.transition_state_machine :failed, reason: connection_state_change.reason
|
244
|
+
end
|
193
245
|
end
|
194
246
|
end
|
195
247
|
|
@@ -216,12 +268,16 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
216
268
|
end
|
217
269
|
|
218
270
|
describe '#connect' do
|
219
|
-
let(:
|
271
|
+
let(:timeout) { 1.5 }
|
220
272
|
|
221
|
-
|
222
|
-
|
223
|
-
|
273
|
+
let(:client_options) do
|
274
|
+
default_options.merge(
|
275
|
+
log_level: :none,
|
276
|
+
realtime_request_timeout: timeout
|
277
|
+
)
|
278
|
+
end
|
224
279
|
|
280
|
+
before do
|
225
281
|
connection.on(:connected) { raise "Connection should not open in this test as CONNECTED ProtocolMessage is never received" }
|
226
282
|
|
227
283
|
connection.once(:connecting) do
|
@@ -231,13 +287,11 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
231
287
|
end
|
232
288
|
|
233
289
|
context 'connection opening times out' do
|
234
|
-
let(:client_options) { client_failure_options }
|
235
|
-
|
236
290
|
it 'attempts to reconnect' do
|
237
291
|
started_at = Time.now
|
238
292
|
|
239
293
|
connection.once(:disconnected) do
|
240
|
-
expect(Time.now.to_f - started_at.to_f).to be >
|
294
|
+
expect(Time.now.to_f - started_at.to_f).to be > timeout
|
241
295
|
connection.once(:connecting) do
|
242
296
|
stop_reactor
|
243
297
|
end
|
@@ -246,21 +300,15 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
246
300
|
connection.connect
|
247
301
|
end
|
248
302
|
|
249
|
-
it 'calls the errback of the returned Deferrable object when first connection attempt fails' do
|
250
|
-
connection.connect.errback do |error|
|
251
|
-
expect(connection.state).to eq(:disconnected)
|
252
|
-
stop_reactor
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
303
|
context 'when retry intervals are stubbed to attempt reconnection quickly' do
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
304
|
+
let(:client_options) do
|
305
|
+
default_options.merge(
|
306
|
+
log_level: :error,
|
307
|
+
disconnected_retry_timeout: 0.1,
|
308
|
+
suspended_retry_timeout: 0.1,
|
309
|
+
connection_state_ttl: 0.2,
|
310
|
+
realtime_host: 'non.existent.host'
|
311
|
+
)
|
264
312
|
end
|
265
313
|
|
266
314
|
it 'never calls the provided success block', em_timeout: 10 do
|
@@ -268,8 +316,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
268
316
|
raise 'success block should not have been called'
|
269
317
|
end
|
270
318
|
|
271
|
-
connection.once(:
|
272
|
-
|
319
|
+
connection.once(:suspended) do
|
320
|
+
connection.once(:suspended) do
|
321
|
+
stop_reactor
|
322
|
+
end
|
273
323
|
end
|
274
324
|
end
|
275
325
|
end
|
@@ -315,14 +365,16 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
315
365
|
context 'and subsequently fails to reconnect' do
|
316
366
|
let(:retry_every) { 1.5 }
|
317
367
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
368
|
+
let(:client_options) do
|
369
|
+
default_options.merge(
|
370
|
+
log_level: :none,
|
371
|
+
disconnected_retry_timeout: retry_every,
|
372
|
+
suspended_retry_timeout: retry_every,
|
373
|
+
connection_state_ttl: 60
|
374
|
+
)
|
323
375
|
end
|
324
376
|
|
325
|
-
it "retries every #{Ably::Realtime::Connection::
|
377
|
+
it "retries every #{Ably::Realtime::Connection::DEFAULTS.fetch(:disconnected_retry_timeout)} seconds" do
|
326
378
|
fail_if_suspended_or_failed
|
327
379
|
|
328
380
|
stubbed_first_attempt = false
|
@@ -382,26 +434,52 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
382
434
|
end
|
383
435
|
|
384
436
|
context 'after successfully reconnecting and resuming' do
|
385
|
-
it 'retains connection_id and connection_key' do
|
386
|
-
previous_connection_id = nil
|
387
|
-
previous_connection_key = nil
|
388
|
-
|
437
|
+
it 'retains connection_id and updates the connection_key' do
|
389
438
|
connection.once(:connected) do
|
390
|
-
previous_connection_id
|
391
|
-
previous_connection_key = connection.key
|
439
|
+
previous_connection_id = connection.id
|
392
440
|
connection.transport.close_connection_after_writing
|
393
441
|
|
442
|
+
expect(connection).to receive(:configure_new).with(previous_connection_id, anything, anything).and_call_original
|
443
|
+
|
394
444
|
connection.once(:connected) do
|
395
|
-
|
396
|
-
# wVIsgTHAB1UvXh7z-1991d8586 becomes wVIsgTHAB1UvXh7z-1990d8586 after resume
|
397
|
-
expect(connection.key[/^\w{5,}-/, 0]).to_not be_nil
|
398
|
-
expect(connection.key[/^\w{5,}-/, 0]).to eql(previous_connection_key[/^\w{5,}-/, 0])
|
445
|
+
expect(connection.key).to_not be_nil
|
399
446
|
expect(connection.id).to eql(previous_connection_id)
|
400
447
|
stop_reactor
|
401
448
|
end
|
402
449
|
end
|
403
450
|
end
|
404
451
|
|
452
|
+
it 'emits any error received from Ably but leaves the channels attached' do
|
453
|
+
emitted_error = nil
|
454
|
+
channel.attach do
|
455
|
+
connection.transport.close_connection_after_writing
|
456
|
+
|
457
|
+
connection.once(:connecting) do
|
458
|
+
connection.__incoming_protocol_msgbus__.unsubscribe
|
459
|
+
connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
460
|
+
allow(protocol_message).to receive(:error).and_return(Ably::Exceptions::Standard.new('Injected error'))
|
461
|
+
end
|
462
|
+
# Create a new message dispatcher that subscribes to ProtocolMessages after the previous subscription allowing us
|
463
|
+
# to modify the ProtocolMessage
|
464
|
+
Ably::Realtime::Client::IncomingMessageDispatcher.new(client, connection)
|
465
|
+
end
|
466
|
+
|
467
|
+
connection.once(:connected) do
|
468
|
+
EM.add_timer(0.5) do
|
469
|
+
expect(emitted_error).to be_a(Ably::Exceptions::Standard)
|
470
|
+
expect(emitted_error.message).to match(/Injected error/)
|
471
|
+
expect(connection.error_reason).to be_a(Ably::Exceptions::Standard)
|
472
|
+
expect(channel).to be_attached
|
473
|
+
stop_reactor
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
connection.once(:error) do |error|
|
478
|
+
emitted_error = error
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
405
483
|
it 'retains channel subscription state' do
|
406
484
|
messages_received = false
|
407
485
|
|
@@ -527,27 +605,28 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
527
605
|
end
|
528
606
|
|
529
607
|
describe 'fallback host feature' do
|
530
|
-
let(:retry_every_for_tests) { 0.
|
531
|
-
let(:max_time_in_state_for_tests) { 0.
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
608
|
+
let(:retry_every_for_tests) { 0.2 }
|
609
|
+
let(:max_time_in_state_for_tests) { 0.59 }
|
610
|
+
|
611
|
+
let(:timeout_options) do
|
612
|
+
default_options.merge(
|
613
|
+
environment: :production,
|
614
|
+
log_level: :none,
|
615
|
+
disconnected_retry_timeout: retry_every_for_tests,
|
616
|
+
suspended_retry_timeout: retry_every_for_tests,
|
617
|
+
connection_state_ttl: max_time_in_state_for_tests
|
618
|
+
)
|
540
619
|
end
|
541
620
|
|
542
621
|
# Retry immediately and then wait retry_every before every subsequent attempt
|
543
|
-
let(:expected_retry_attempts)
|
622
|
+
let(:expected_retry_attempts) { 1 + (max_time_in_state_for_tests / retry_every_for_tests).round }
|
544
623
|
|
545
624
|
let(:retry_count_for_one_state) { 1 + expected_retry_attempts } # initial connect then disconnected
|
546
|
-
let(:retry_count_for_all_states) { 1 + expected_retry_attempts
|
625
|
+
let(:retry_count_for_all_states) { 1 + expected_retry_attempts + 1 } # initial connection, disconnected & then one suspended attempt
|
547
626
|
|
548
627
|
context 'with custom realtime websocket host option' do
|
549
628
|
let(:expected_host) { 'this.host.does.not.exist' }
|
550
|
-
let(:client_options) {
|
629
|
+
let(:client_options) { timeout_options.merge(realtime_host: expected_host) }
|
551
630
|
|
552
631
|
it 'never uses a fallback host' do
|
553
632
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host|
|
@@ -555,15 +634,17 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
555
634
|
raise EventMachine::ConnectionError
|
556
635
|
end
|
557
636
|
|
558
|
-
connection.
|
559
|
-
|
637
|
+
connection.once(:suspended) do
|
638
|
+
connection.once(:suspended) do
|
639
|
+
stop_reactor
|
640
|
+
end
|
560
641
|
end
|
561
642
|
end
|
562
643
|
end
|
563
644
|
|
564
645
|
context 'with custom realtime websocket port option' do
|
565
646
|
let(:custom_port) { 666}
|
566
|
-
let(:client_options) {
|
647
|
+
let(:client_options) { timeout_options.merge(tls_port: custom_port) }
|
567
648
|
|
568
649
|
it 'never uses a fallback host' do
|
569
650
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host, port|
|
@@ -571,8 +652,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
571
652
|
raise EventMachine::ConnectionError
|
572
653
|
end
|
573
654
|
|
574
|
-
connection.
|
575
|
-
|
655
|
+
connection.once(:suspended) do
|
656
|
+
connection.once(:suspended) do
|
657
|
+
stop_reactor
|
658
|
+
end
|
576
659
|
end
|
577
660
|
end
|
578
661
|
end
|
@@ -580,7 +663,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
580
663
|
context 'with non-production environment' do
|
581
664
|
let(:environment) { 'sandbox' }
|
582
665
|
let(:expected_host) { "#{environment}-#{Ably::Realtime::Client::DOMAIN}" }
|
583
|
-
let(:client_options) {
|
666
|
+
let(:client_options) { timeout_options.merge(environment: environment) }
|
584
667
|
|
585
668
|
it 'never uses a fallback host' do
|
586
669
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host|
|
@@ -588,8 +671,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
588
671
|
raise EventMachine::ConnectionError
|
589
672
|
end
|
590
673
|
|
591
|
-
connection.
|
592
|
-
|
674
|
+
connection.once(:suspended) do
|
675
|
+
connection.once(:suspended) do
|
676
|
+
stop_reactor
|
677
|
+
end
|
593
678
|
end
|
594
679
|
end
|
595
680
|
end
|
@@ -601,7 +686,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
601
686
|
end
|
602
687
|
|
603
688
|
let(:expected_host) { Ably::Realtime::Client::DOMAIN }
|
604
|
-
let(:client_options) {
|
689
|
+
let(:client_options) { timeout_options.merge(environment: nil) }
|
605
690
|
|
606
691
|
let(:fallback_hosts_used) { Array.new }
|
607
692
|
|
@@ -616,8 +701,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
616
701
|
raise EventMachine::ConnectionError
|
617
702
|
end
|
618
703
|
|
619
|
-
connection.
|
620
|
-
|
704
|
+
connection.once(:suspended) do
|
705
|
+
connection.once(:suspended) do
|
706
|
+
stop_reactor
|
707
|
+
end
|
621
708
|
end
|
622
709
|
end
|
623
710
|
end
|
@@ -629,8 +716,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
629
716
|
|
630
717
|
it 'uses a fallback host on every subsequent disconnected attempt until suspended' do
|
631
718
|
request = 0
|
632
|
-
|
633
|
-
expect(EventMachine).to receive(:connect).exactly(retry_count_for_one_state + 1).times do |host|
|
719
|
+
expect(EventMachine).to receive(:connect).exactly(retry_count_for_one_state).times do |host|
|
634
720
|
if request == 0
|
635
721
|
expect(host).to eql(expected_host)
|
636
722
|
else
|
@@ -640,7 +726,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
640
726
|
raise EventMachine::ConnectionError
|
641
727
|
end
|
642
728
|
|
643
|
-
connection.
|
729
|
+
connection.once(:suspended) do
|
644
730
|
fallback_hosts_used.pop # remove suspended attempt host
|
645
731
|
expect(fallback_hosts_used.uniq).to match_array(custom_hosts)
|
646
732
|
stop_reactor
|
@@ -649,20 +735,25 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
649
735
|
|
650
736
|
it 'uses the primary host when suspended, and a fallback host on every subsequent suspended attempt' do
|
651
737
|
request = 0
|
652
|
-
expect(EventMachine).to receive(:connect).
|
738
|
+
expect(EventMachine).to receive(:connect).at_least(:once) do |host|
|
653
739
|
if request == 0 || request == expected_retry_attempts + 1
|
654
740
|
expect(host).to eql(expected_host)
|
655
741
|
else
|
656
742
|
expect(custom_hosts).to include(host)
|
657
|
-
fallback_hosts_used << host
|
743
|
+
fallback_hosts_used << host if @suspended
|
658
744
|
end
|
659
745
|
request += 1
|
660
746
|
raise EventMachine::ConnectionError
|
661
747
|
end
|
662
748
|
|
663
|
-
connection.on(:
|
664
|
-
|
665
|
-
|
749
|
+
connection.on(:suspended) do
|
750
|
+
@suspended ||= 0
|
751
|
+
@suspended += 1
|
752
|
+
|
753
|
+
if @suspended > 3
|
754
|
+
expect(fallback_hosts_used.uniq).to match_array(custom_hosts)
|
755
|
+
stop_reactor
|
756
|
+
end
|
666
757
|
end
|
667
758
|
end
|
668
759
|
end
|