ably 0.8.3 → 0.8.4
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/CHANGELOG.md +13 -3
- data/lib/ably/auth.rb +1 -1
- data/lib/ably/exceptions.rb +3 -0
- data/lib/ably/models/channel_state_change.rb +41 -0
- data/lib/ably/models/connection_state_change.rb +43 -0
- data/lib/ably/models/message.rb +1 -1
- data/lib/ably/models/presence_message.rb +1 -1
- data/lib/ably/models/protocol_message.rb +2 -1
- data/lib/ably/modules/state_emitter.rb +4 -1
- data/lib/ably/modules/uses_state_machine.rb +28 -4
- data/lib/ably/realtime/channel.rb +11 -3
- data/lib/ably/realtime/channel/channel_manager.rb +24 -4
- data/lib/ably/realtime/channel/channel_state_machine.rb +20 -11
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +4 -4
- data/lib/ably/realtime/connection.rb +1 -0
- data/lib/ably/realtime/connection/connection_manager.rb +33 -21
- data/lib/ably/realtime/connection/connection_state_machine.rb +24 -16
- data/lib/ably/rest/channel.rb +3 -2
- data/lib/ably/util/crypto.rb +15 -0
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_spec.rb +155 -9
- data/spec/acceptance/realtime/client_spec.rb +2 -2
- data/spec/acceptance/realtime/connection_failures_spec.rb +8 -4
- data/spec/acceptance/realtime/connection_spec.rb +122 -11
- data/spec/acceptance/realtime/message_spec.rb +119 -3
- data/spec/acceptance/realtime/presence_spec.rb +34 -13
- data/spec/acceptance/rest/channel_spec.rb +9 -0
- data/spec/acceptance/rest/client_spec.rb +10 -0
- data/spec/unit/models/channel_state_change_spec.rb +44 -0
- data/spec/unit/models/connection_state_change_spec.rb +54 -0
- data/spec/unit/util/crypto_spec.rb +18 -0
- metadata +8 -2
@@ -31,8 +31,8 @@ describe Ably::Realtime::Client, :event_machine do
|
|
31
31
|
it 'fails to connect because a private key cannot be sent over a non-secure connection' do
|
32
32
|
connection.on(:connected) { raise 'Should not have connected' }
|
33
33
|
|
34
|
-
connection.on(:failed) do |
|
35
|
-
expect(
|
34
|
+
connection.on(:failed) do |connection_state_change|
|
35
|
+
expect(connection_state_change.reason).to be_a(Ably::Exceptions::InsecureRequest)
|
36
36
|
stop_reactor
|
37
37
|
end
|
38
38
|
end
|
@@ -24,7 +24,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
24
24
|
let(:invalid_key) { 'not_an_app.invalid_key_name:invalid_key_value' }
|
25
25
|
|
26
26
|
it 'enters the failed state and returns a not found error' do
|
27
|
-
connection.on(:failed) do |
|
27
|
+
connection.on(:failed) do |connection_state_change|
|
28
|
+
error = connection_state_change.reason
|
28
29
|
expect(connection.state).to eq(:failed)
|
29
30
|
# TODO: Check error type is an InvalidToken exception
|
30
31
|
expect(error.status).to eq(404)
|
@@ -38,7 +39,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
38
39
|
let(:invalid_key) { "#{app_id}.invalid_key_name:invalid_key_value" }
|
39
40
|
|
40
41
|
it 'enters the failed state and returns an authorization error' do
|
41
|
-
connection.on(:failed) do |
|
42
|
+
connection.on(:failed) do |connection_state_change|
|
43
|
+
error = connection_state_change.reason
|
42
44
|
expect(connection.state).to eq(:failed)
|
43
45
|
# TODO: Check error type is a TokenNotFOund exception
|
44
46
|
expect(error.status).to eq(401)
|
@@ -182,7 +184,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
182
184
|
context '#error_reason' do
|
183
185
|
[:disconnected, :suspended, :failed].each do |state|
|
184
186
|
it "contains the error when state is #{state}" do
|
185
|
-
connection.on(state) do |
|
187
|
+
connection.on(state) do |connection_state_change|
|
188
|
+
error = connection_state_change.reason
|
186
189
|
expect(connection.error_reason).to eq(error)
|
187
190
|
expect(connection.error_reason.code).to eql(80000)
|
188
191
|
stop_reactor
|
@@ -488,7 +491,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
488
491
|
when_all(*channels.map(&:attach)) do
|
489
492
|
detached_channels = []
|
490
493
|
channels.each do |channel|
|
491
|
-
channel.on(:detached) do |
|
494
|
+
channel.on(:detached) do |channel_state_change|
|
495
|
+
error = channel_state_change.reason
|
492
496
|
expect(error.message).to match(/Invalid connection key/i)
|
493
497
|
detached_channels << channel
|
494
498
|
next unless detached_channels.count == channel_count
|
@@ -127,8 +127,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
127
127
|
it 'renews the token on connect, and only makes one subsequent attempt to obtain a new token' do
|
128
128
|
expect(client.rest_client.auth).to receive(:authorise).at_least(:twice).and_call_original
|
129
129
|
connection.once(:disconnected) do
|
130
|
-
connection.once(:failed) do |
|
131
|
-
expect(
|
130
|
+
connection.once(:failed) do |connection_state_change|
|
131
|
+
expect(connection_state_change.reason.code).to eql(40140) # token expired
|
132
132
|
stop_reactor
|
133
133
|
end
|
134
134
|
end
|
@@ -167,8 +167,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
167
167
|
|
168
168
|
connection.once(:connected) do
|
169
169
|
started_at = Time.now
|
170
|
-
connection.once(:disconnected) do |
|
171
|
-
expect(
|
170
|
+
connection.once(:disconnected) do |connection_state_change|
|
171
|
+
expect(connection_state_change.reason.code).to eq(40140) # Token expired
|
172
172
|
|
173
173
|
# Token has expired, so now ensure it is not used again
|
174
174
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', original_token_expiry_buffer
|
@@ -178,7 +178,6 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
178
178
|
expect(client.auth.current_token_details).to_not be_expired
|
179
179
|
expect(Time.now - started_at >= ttl)
|
180
180
|
expect(original_token).to be_expired
|
181
|
-
expect(error.code).to eql(40140) # token expired
|
182
181
|
stop_reactor
|
183
182
|
end
|
184
183
|
end
|
@@ -922,12 +921,12 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
922
921
|
expect(connection.__outgoing_message_queue__).to be_empty
|
923
922
|
channel.publish 'test'
|
924
923
|
|
925
|
-
EventMachine.
|
924
|
+
EventMachine.next_tick do
|
926
925
|
expect(connection.__outgoing_message_queue__).to_not be_empty
|
927
926
|
end
|
928
927
|
|
929
928
|
connection.once(:connected) do
|
930
|
-
EventMachine.add_timer(0.
|
929
|
+
EventMachine.add_timer(0.1) do
|
931
930
|
expect(connection.__outgoing_message_queue__).to be_empty
|
932
931
|
stop_reactor
|
933
932
|
end
|
@@ -940,6 +939,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
940
939
|
end
|
941
940
|
|
942
941
|
context 'when connection enters the :suspended state' do
|
942
|
+
let(:client_options) { default_options.merge(:log_level => :fatal) }
|
943
|
+
|
943
944
|
before do
|
944
945
|
# Reconfigure client library retry periods so that client stays in suspended state
|
945
946
|
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
|
@@ -956,13 +957,21 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
956
957
|
stop_reactor
|
957
958
|
end
|
958
959
|
|
960
|
+
close_connection_proc = Proc.new do
|
961
|
+
EventMachine.add_timer(0.001) do
|
962
|
+
if connection.transport.nil?
|
963
|
+
close_connection_proc.call
|
964
|
+
else
|
965
|
+
connection.transport.close_connection_after_writing
|
966
|
+
end
|
967
|
+
end
|
968
|
+
end
|
969
|
+
|
959
970
|
# Keep disconnecting the websocket transport after it attempts reconnection
|
960
|
-
connection.transport.close_connection_after_writing
|
961
971
|
connection.on(:connecting) do
|
962
|
-
|
963
|
-
connection.transport.close_connection_after_writing
|
964
|
-
end
|
972
|
+
close_connection_proc.call
|
965
973
|
end
|
974
|
+
close_connection_proc.call
|
966
975
|
end
|
967
976
|
end
|
968
977
|
end
|
@@ -979,5 +988,107 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
979
988
|
end
|
980
989
|
end
|
981
990
|
end
|
991
|
+
|
992
|
+
context 'connection state change' do
|
993
|
+
it 'emits a ConnectionStateChange object' do
|
994
|
+
connection.on(:connected) do |connection_state_change|
|
995
|
+
expect(connection_state_change).to be_a(Ably::Models::ConnectionStateChange)
|
996
|
+
stop_reactor
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
context 'ConnectionStateChange object' do
|
1001
|
+
it 'has current state' do
|
1002
|
+
connection.on(:connected) do |connection_state_change|
|
1003
|
+
expect(connection_state_change.current).to eq(:connected)
|
1004
|
+
stop_reactor
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it 'has a previous state' do
|
1009
|
+
connection.on(:connected) do |connection_state_change|
|
1010
|
+
expect(connection_state_change.previous).to eq(:connecting)
|
1011
|
+
stop_reactor
|
1012
|
+
end
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
it 'contains a private API protocol_message attribute that is used for special state change events', :api_private do
|
1016
|
+
connection.on(:connected) do |connection_state_change|
|
1017
|
+
expect(connection_state_change.protocol_message).to be_a(Ably::Models::ProtocolMessage)
|
1018
|
+
expect(connection_state_change.reason).to be_nil
|
1019
|
+
stop_reactor
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
|
1023
|
+
it 'has an empty reason when there is no error' do
|
1024
|
+
connection.on(:closed) do |connection_state_change|
|
1025
|
+
expect(connection_state_change.reason).to be_nil
|
1026
|
+
stop_reactor
|
1027
|
+
end
|
1028
|
+
connection.connect do
|
1029
|
+
connection.close
|
1030
|
+
end
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
context 'on failure' do
|
1034
|
+
let(:client_options) { default_options.merge(log_level: :none) }
|
1035
|
+
|
1036
|
+
it 'has a reason Error object when there is an error on the connection' do
|
1037
|
+
connection.on(:failed) do |connection_state_change|
|
1038
|
+
expect(connection_state_change.reason).to be_a(Ably::Exceptions::BaseAblyException)
|
1039
|
+
stop_reactor
|
1040
|
+
end
|
1041
|
+
connection.connect do
|
1042
|
+
error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
|
1043
|
+
client.connection.manager.error_received_from_server error
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
context 'retry_in' do
|
1049
|
+
let(:client_options) { default_options.merge(log_level: :debug) }
|
1050
|
+
|
1051
|
+
it 'is nil when a retry is not required' do
|
1052
|
+
connection.on(:connected) do |connection_state_change|
|
1053
|
+
expect(connection_state_change.retry_in).to be_nil
|
1054
|
+
stop_reactor
|
1055
|
+
end
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
it 'is 0 when first attempt to connect fails' do
|
1059
|
+
connection.once(:connecting) do
|
1060
|
+
connection.once(:disconnected) do |connection_state_change|
|
1061
|
+
expect(connection_state_change.retry_in).to eql(0)
|
1062
|
+
stop_reactor
|
1063
|
+
end
|
1064
|
+
EventMachine.add_timer(0.001) { connection.transport.unbind }
|
1065
|
+
end
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
it 'is 0 when an immediate reconnect will occur' do
|
1069
|
+
connection.once(:connected) do
|
1070
|
+
connection.once(:disconnected) do |connection_state_change|
|
1071
|
+
expect(connection_state_change.retry_in).to eql(0)
|
1072
|
+
stop_reactor
|
1073
|
+
end
|
1074
|
+
connection.transport.unbind
|
1075
|
+
end
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
it 'contains the next retry period when an immediate reconnect will not occur' do
|
1079
|
+
connection.once(:connected) do
|
1080
|
+
connection.once(:connecting) do
|
1081
|
+
connection.once(:disconnected) do |connection_state_change|
|
1082
|
+
expect(connection_state_change.retry_in).to be > 0
|
1083
|
+
stop_reactor
|
1084
|
+
end
|
1085
|
+
EventMachine.add_timer(0.001) { connection.transport.unbind }
|
1086
|
+
end
|
1087
|
+
connection.transport.unbind
|
1088
|
+
end
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
end
|
1092
|
+
end
|
982
1093
|
end
|
983
1094
|
end
|
@@ -181,10 +181,14 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
181
181
|
|
182
182
|
context 'with :echo_messages option set to false' do
|
183
183
|
let(:no_echo_client) do
|
184
|
-
Ably::Realtime::Client.new(default_options.merge(echo_messages: false))
|
184
|
+
Ably::Realtime::Client.new(default_options.merge(echo_messages: false, log_level: :debug))
|
185
185
|
end
|
186
186
|
let(:no_echo_channel) { no_echo_client.channel(channel_name) }
|
187
187
|
|
188
|
+
let(:rest_client) do
|
189
|
+
Ably::Rest::Client.new(default_options.merge(log_level: :debug))
|
190
|
+
end
|
191
|
+
|
188
192
|
it 'will not echo messages to the client but will still broadcast messages to other connected clients', em_timeout: 10 do
|
189
193
|
channel.attach do |echo_channel|
|
190
194
|
no_echo_channel.attach do
|
@@ -196,13 +200,27 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
196
200
|
|
197
201
|
echo_channel.subscribe('test_event') do |message|
|
198
202
|
expect(message.data).to eql(payload)
|
199
|
-
EventMachine.add_timer(1) do
|
203
|
+
EventMachine.add_timer(1.5) do
|
200
204
|
stop_reactor
|
201
205
|
end
|
202
206
|
end
|
203
207
|
end
|
204
208
|
end
|
205
209
|
end
|
210
|
+
|
211
|
+
it 'will not echo messages to the client from other REST clients publishing using that connection_ID', em_timeout: 10 do
|
212
|
+
skip 'Waiting on realtime#285 to be resolved'
|
213
|
+
no_echo_channel.attach do
|
214
|
+
no_echo_channel.subscribe('test_event') do |message|
|
215
|
+
fail "Message should not have been echoed back"
|
216
|
+
end
|
217
|
+
|
218
|
+
rest_client.channel(channel_name).publish('test_event', nil, connection_id: no_echo_client.connection.id)
|
219
|
+
EventMachine.add_timer(1.5) do
|
220
|
+
stop_reactor
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
206
224
|
end
|
207
225
|
end
|
208
226
|
|
@@ -257,7 +275,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
257
275
|
|
258
276
|
context 'without suitable publishing permissions' do
|
259
277
|
let(:restricted_client) do
|
260
|
-
Ably::Realtime::Client.new(options.merge(key: restricted_api_key, environment: environment, protocol: protocol))
|
278
|
+
Ably::Realtime::Client.new(options.merge(key: restricted_api_key, environment: environment, protocol: protocol, :log_level => :error))
|
261
279
|
end
|
262
280
|
let(:restricted_channel) { restricted_client.channel("cansubscribe:example") }
|
263
281
|
let(:payload) { 'Test message without permission to publish' }
|
@@ -569,5 +587,103 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
569
587
|
end
|
570
588
|
end
|
571
589
|
end
|
590
|
+
|
591
|
+
describe 'when message is published, the connection disconnects before the ACK is received, and the connection is resumed' do
|
592
|
+
let(:event_name) { random_str }
|
593
|
+
let(:message_state) { [] }
|
594
|
+
let(:connection) { client.connection }
|
595
|
+
let(:client_options) { default_options.merge(:log_level => :debug) }
|
596
|
+
let(:msgs_received) { [] }
|
597
|
+
|
598
|
+
it 'publishes the message again, later receives the ACK and only one message is ever received from Ably' do
|
599
|
+
on_reconnected = Proc.new do
|
600
|
+
expect(message_state).to be_empty
|
601
|
+
EventMachine.add_timer(2) do
|
602
|
+
expect(message_state).to contain_exactly(:delivered)
|
603
|
+
# TODO: Uncomment once issue realtime#42 is resolved
|
604
|
+
# expect(msgs_received.length).to eql(1)
|
605
|
+
stop_reactor
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
connection.once(:connected) do
|
610
|
+
connection.transport.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
611
|
+
if protocol_message.messages.find { |message| message.name == event_name }
|
612
|
+
EventMachine.add_timer(0.001) do
|
613
|
+
connection.transport.unbind # trigger failure
|
614
|
+
expect(message_state).to be_empty
|
615
|
+
connection.once :connected, &on_reconnected
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
channel.publish(event_name).tap do |deferrable|
|
622
|
+
deferrable.callback { message_state << :delivered }
|
623
|
+
deferrable.errback do
|
624
|
+
raise 'Message delivery should not fail'
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
channel.subscribe do |message|
|
629
|
+
msgs_received << message
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
describe 'when message is published, the connection disconnects before the ACK is received' do
|
635
|
+
let(:connection) { client.connection }
|
636
|
+
let(:event_name) { random_str }
|
637
|
+
|
638
|
+
describe 'the connection becomes suspended' do
|
639
|
+
let(:client_options) { default_options.merge(:log_level => :fatal) }
|
640
|
+
|
641
|
+
it 'calls the errback for all messages' do
|
642
|
+
connection.once(:connected) do
|
643
|
+
connection.transport.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
644
|
+
if protocol_message.messages.find { |message| message.name == event_name }
|
645
|
+
EventMachine.add_timer(0.001) do
|
646
|
+
connection.transition_state_machine :suspended
|
647
|
+
end
|
648
|
+
end
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
channel.publish(event_name).tap do |deferrable|
|
653
|
+
deferrable.callback do
|
654
|
+
raise 'Message delivery should not happen'
|
655
|
+
end
|
656
|
+
deferrable.errback do
|
657
|
+
stop_reactor
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
describe 'the connection becomes failed' do
|
664
|
+
let(:client_options) { default_options.merge(:log_level => :none) }
|
665
|
+
|
666
|
+
it 'calls the errback for all messages' do
|
667
|
+
connection.once(:connected) do
|
668
|
+
connection.transport.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
669
|
+
if protocol_message.messages.find { |message| message.name == event_name }
|
670
|
+
EventMachine.add_timer(0.001) do
|
671
|
+
connection.transition_state_machine :failed, reason: RuntimeError.new
|
672
|
+
end
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
channel.publish(event_name).tap do |deferrable|
|
678
|
+
deferrable.callback do
|
679
|
+
raise 'Message delivery should not happen'
|
680
|
+
end
|
681
|
+
deferrable.errback do
|
682
|
+
stop_reactor
|
683
|
+
end
|
684
|
+
end
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
572
688
|
end
|
573
689
|
end
|
@@ -40,18 +40,29 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
unless expected_state == :left
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
channel_client_one.
|
47
|
-
|
48
|
-
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE
|
43
|
+
it 'raise an exception if the channel is detached' do
|
44
|
+
setup_test(method_name, args, options) do
|
45
|
+
channel_client_one.attach do
|
46
|
+
channel_client_one.transition_state_machine :detaching
|
47
|
+
channel_client_one.once(:detached) do
|
48
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.detached/i
|
49
49
|
stop_reactor
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'raise an exception if the channel is failed' do
|
56
|
+
setup_test(method_name, args, options) do
|
57
|
+
channel_client_one.attach do
|
58
|
+
channel_client_one.transition_state_machine :failed
|
59
|
+
expect(channel_client_one.state).to eq(:failed)
|
60
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.failed/i
|
61
|
+
stop_reactor
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
55
66
|
it 'implicitly attaches the channel' do
|
56
67
|
expect(channel_client_one).to_not be_attached
|
57
68
|
presence_client_one.public_send(method_name, args) do
|
@@ -1061,16 +1072,25 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1061
1072
|
presence_client_one.get { raise 'Intentional exception' }
|
1062
1073
|
end
|
1063
1074
|
|
1064
|
-
|
1065
|
-
|
1066
|
-
channel_client_one.
|
1067
|
-
|
1068
|
-
expect { presence_client_one.get }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE
|
1075
|
+
it 'raise an exception if the channel is detached' do
|
1076
|
+
channel_client_one.attach do
|
1077
|
+
channel_client_one.transition_state_machine :detaching
|
1078
|
+
channel_client_one.once(:detached) do
|
1079
|
+
expect { presence_client_one.get }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.detached/i
|
1069
1080
|
stop_reactor
|
1070
1081
|
end
|
1071
1082
|
end
|
1072
1083
|
end
|
1073
1084
|
|
1085
|
+
it 'raise an exception if the channel is failed' do
|
1086
|
+
channel_client_one.attach do
|
1087
|
+
channel_client_one.transition_state_machine :failed
|
1088
|
+
expect(channel_client_one.state).to eq(:failed)
|
1089
|
+
expect { presence_client_one.get }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.failed/i
|
1090
|
+
stop_reactor
|
1091
|
+
end
|
1092
|
+
end
|
1093
|
+
|
1074
1094
|
context 'during a sync' do
|
1075
1095
|
let(:pages) { 2 }
|
1076
1096
|
let(:members_per_page) { 100 }
|
@@ -1120,8 +1140,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1120
1140
|
if protocol_message.action == :sync
|
1121
1141
|
# prevent any more SYNC messages coming through
|
1122
1142
|
client_two.connection.transport.__incoming_protocol_msgbus__.unsubscribe
|
1123
|
-
channel_client_two.
|
1124
|
-
channel_client_two.
|
1143
|
+
channel_client_two.transition_state_machine :detaching
|
1144
|
+
channel_client_two.transition_state_machine :detached
|
1125
1145
|
end
|
1126
1146
|
end
|
1127
1147
|
end
|
@@ -1565,6 +1585,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1565
1585
|
context 'connection failure mid-way through a large member sync' do
|
1566
1586
|
let(:members_count) { 400 }
|
1567
1587
|
let(:sync_pages_received) { [] }
|
1588
|
+
let(:client_options) { default_options.merge(log_level: :error) }
|
1568
1589
|
|
1569
1590
|
it 'resumes the SYNC operation', em_timeout: 15 do
|
1570
1591
|
when_all(*members_count.times.map do |index|
|