ably 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -4
- data/CHANGELOG.md +18 -1
- data/README.md +9 -1
- data/ably.gemspec +3 -3
- data/lib/ably/realtime/client.rb +4 -3
- data/lib/ably/realtime/connection.rb +24 -15
- data/lib/ably/realtime/connection/connection_manager.rb +0 -2
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/auth_spec.rb +11 -9
- data/spec/acceptance/realtime/channel_history_spec.rb +26 -20
- data/spec/acceptance/realtime/connection_failures_spec.rb +3 -3
- data/spec/acceptance/realtime/connection_spec.rb +116 -14
- data/spec/acceptance/realtime/message_spec.rb +15 -13
- data/spec/acceptance/realtime/presence_spec.rb +196 -162
- data/spec/acceptance/realtime/push_admin_spec.rb +6 -4
- data/spec/acceptance/rest/channel_spec.rb +37 -0
- data/spec/acceptance/rest/channels_spec.rb +6 -0
- data/spec/acceptance/rest/message_spec.rb +7 -25
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/realtime/connection_spec.rb +1 -1
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26f56201f9faae28b9b74ef9223e8d50c049a25d065f80d8612ce0013da46783
|
4
|
+
data.tar.gz: f74af9b0f0178576e41094fccf80821983da0b896e6bd7667fe534abe0d096bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a4c6c4006a176c01eacd9f38d9f11a61fb7f64880a764a663eca26e2ed2b7806203f972edf7cb5f0dec1034e6776d6b6dac459766ba920cc09ea156022640a9
|
7
|
+
data.tar.gz: 59d33ebc03521cf47449140715b5506dca17ac6b3708b914b6b0987d038c56667231086c8ff81c8d740d8a62c4474ac78c9839360b795e2d5c8f779ad972e3a5
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,24 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [v1.1.
|
3
|
+
## [v1.1.1](https://github.com/ably/ably-ruby/tree/v1.1.1)
|
4
4
|
|
5
|
+
[Full Changelog](https://github.com/ably/ably-ruby/compare/v1.1.0...v1.1.1)
|
6
|
+
|
7
|
+
**Implemented enhancements:**
|
8
|
+
|
9
|
+
- Support transient publishes as part of 1.1 spec [\#164](https://github.com/ably/ably-ruby/issues/164)
|
10
|
+
|
11
|
+
**Fixed bugs:**
|
12
|
+
|
13
|
+
- RTN16b recovery not fully implemented [\#180](https://github.com/ably/ably-ruby/issues/180)
|
14
|
+
- Publishing a high number of messages before connected results in lost messages [\#179](https://github.com/ably/ably-ruby/issues/179)
|
15
|
+
|
16
|
+
**Merged pull requests:**
|
17
|
+
|
18
|
+
- msgSerial fixes including connection recovery fix [\#181](https://github.com/ably/ably-ruby/pull/181) ([mattheworiordan](https://github.com/mattheworiordan))
|
19
|
+
- Known limitations section in README [\#177](https://github.com/ably/ably-ruby/pull/177) ([Srushtika](https://github.com/Srushtika))
|
20
|
+
|
21
|
+
## [v1.1.0](https://github.com/ably/ably-ruby/tree/v1.1.0) (2019-02-06)
|
5
22
|
[Full Changelog](https://github.com/ably/ably-ruby/compare/v1.0.7...v1.1.0)
|
6
23
|
|
7
24
|
**Fixed bugs:**
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/ably.svg)](http://badge.fury.io/rb/ably)
|
4
4
|
[![Coverage Status](https://coveralls.io/repos/ably/ably-ruby/badge.svg)](https://coveralls.io/r/ably/ably-ruby)
|
5
5
|
|
6
|
-
A Ruby client library for [ably.io](https://www.ably.io), the realtime messaging service.
|
6
|
+
A Ruby client library for [ably.io](https://www.ably.io), the realtime messaging service. This library currently targets the [Ably 1.1 client library specification](https://www.ably.io/documentation/client-lib-development-guide/features/). You can jump to the '[Known Limitations](#known-limitations)' section to see the features this client library does not yet support or [view our client library SDKs feature support matrix](https://www.ably.io/download/sdk-feature-support-matrix) to see the list of all the available features.
|
7
7
|
|
8
8
|
## Supported platforms
|
9
9
|
|
@@ -13,6 +13,14 @@ We regression-test the SDK against a selection of Ruby versions (which we update
|
|
13
13
|
|
14
14
|
If you find any compatibility issues, please [do raise an issue](https://github.com/ably/ably-ruby/issues/new) in this repository or [contact Ably customer support](https://support.ably.io/) for advice.
|
15
15
|
|
16
|
+
## Known Limitations
|
17
|
+
|
18
|
+
This client library is currently *not compatible* with some of the Ably features:
|
19
|
+
|
20
|
+
| Feature |
|
21
|
+
| :--- |
|
22
|
+
| [Custom transportParams](https://www.ably.io/documentation/realtime/connection#client-options) |
|
23
|
+
|
16
24
|
## Documentation
|
17
25
|
|
18
26
|
Visit https://www.ably.io/documentation for a complete API reference and more examples.
|
data/ably.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency 'faraday', '~> 0.12'
|
25
25
|
spec.add_runtime_dependency 'excon', '~> 0.55'
|
26
26
|
|
27
|
-
if RUBY_VERSION.match(/^1
|
27
|
+
if RUBY_VERSION.match(/^1\./)
|
28
28
|
spec.add_runtime_dependency 'json', '< 2.0'
|
29
29
|
else
|
30
30
|
spec.add_runtime_dependency 'json'
|
@@ -33,15 +33,15 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_runtime_dependency 'msgpack', '>= 0.6.2'
|
34
34
|
spec.add_runtime_dependency 'addressable', '>= 2.0.0'
|
35
35
|
|
36
|
-
spec.add_development_dependency 'bundler', '~> 1.3'
|
37
36
|
spec.add_development_dependency 'rake', '~> 11.3'
|
38
37
|
spec.add_development_dependency 'redcarpet', '~> 3.3'
|
39
38
|
spec.add_development_dependency 'rspec', '~> 3.3.0' # version lock, see config.around(:example, :event_machine) in event_machine_helper.rb
|
40
39
|
spec.add_development_dependency 'rspec-retry', '~> 0.6'
|
41
40
|
spec.add_development_dependency 'yard', '~> 0.9'
|
42
41
|
spec.add_development_dependency 'rspec-instafail', '~> 1.0'
|
42
|
+
spec.add_development_dependency 'bundler', '>= 1.3.0'
|
43
43
|
|
44
|
-
if RUBY_VERSION.match(/^1
|
44
|
+
if RUBY_VERSION.match(/^1\./)
|
45
45
|
spec.add_development_dependency 'public_suffix', '~> 1.4.6' # Later versions do not support Ruby 1.9
|
46
46
|
spec.add_development_dependency 'webmock', '2.2'
|
47
47
|
spec.add_development_dependency 'parallel_tests', '~> 2.9.0'
|
data/lib/ably/realtime/client.rb
CHANGED
@@ -110,9 +110,6 @@ module Ably
|
|
110
110
|
end
|
111
111
|
|
112
112
|
@rest_client = Ably::Rest::Client.new(options.merge(realtime_client: self))
|
113
|
-
@auth = Ably::Realtime::Auth.new(self)
|
114
|
-
@channels = Ably::Realtime::Channels.new(self)
|
115
|
-
@connection = Ably::Realtime::Connection.new(self, options)
|
116
113
|
@echo_messages = rest_client.options.fetch(:echo_messages, true) == false ? false : true
|
117
114
|
@queue_messages = rest_client.options.fetch(:queue_messages, true) == false ? false : true
|
118
115
|
@custom_realtime_host = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
|
@@ -120,6 +117,10 @@ module Ably
|
|
120
117
|
@recover = rest_client.options[:recover]
|
121
118
|
|
122
119
|
raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
|
120
|
+
|
121
|
+
@auth = Ably::Realtime::Auth.new(self)
|
122
|
+
@channels = Ably::Realtime::Channels.new(self)
|
123
|
+
@connection = Ably::Realtime::Connection.new(self, options)
|
123
124
|
end
|
124
125
|
|
125
126
|
# Return a {Ably::Realtime::Channel Realtime Channel} for the given name
|
@@ -66,7 +66,7 @@ module Ably
|
|
66
66
|
ensure_state_machine_emits 'Ably::Models::ConnectionStateChange'
|
67
67
|
|
68
68
|
# Expected format for a connection recover key
|
69
|
-
RECOVER_REGEX = /^(?<recover>[
|
69
|
+
RECOVER_REGEX = /^(?<recover>[^:]+):(?<connection_serial>[^:]+):(?<msg_serial>\-?\d+)$/
|
70
70
|
|
71
71
|
# Defaults for automatic connection recovery and timeouts
|
72
72
|
DEFAULTS = {
|
@@ -137,7 +137,6 @@ module Ably
|
|
137
137
|
@client = client
|
138
138
|
@__outgoing_message_queue__ = []
|
139
139
|
@__pending_message_ack_queue__ = []
|
140
|
-
reset_client_serial
|
141
140
|
|
142
141
|
@defaults = DEFAULTS.dup
|
143
142
|
options.each do |key, val|
|
@@ -145,6 +144,17 @@ module Ably
|
|
145
144
|
end if options.kind_of?(Hash)
|
146
145
|
@defaults.freeze
|
147
146
|
|
147
|
+
# If a recover client options is provided, then we need to ensure that the msgSerial matches the
|
148
|
+
# recover serial immediately at client library instantiation. This is done immediately so that any queued
|
149
|
+
# publishes use the correct serial number for these queued messages as well.
|
150
|
+
# There is no harm if the msgSerial is higher than expected if the recover fails.
|
151
|
+
recovery_msg_serial = connection_recover_parts && connection_recover_parts[:msg_serial].to_i
|
152
|
+
if recovery_msg_serial
|
153
|
+
@client_msg_serial = recovery_msg_serial
|
154
|
+
else
|
155
|
+
reset_client_msg_serial
|
156
|
+
end
|
157
|
+
|
148
158
|
Client::IncomingMessageDispatcher.new client, self
|
149
159
|
Client::OutgoingMessageDispatcher.new client, self
|
150
160
|
|
@@ -303,18 +313,17 @@ module Ably
|
|
303
313
|
# @!attribute [r] recovery_key
|
304
314
|
# @return [String] recovery key that can be used by another client to recover this connection with the :recover option
|
305
315
|
def recovery_key
|
306
|
-
"#{key}:#{serial}" if connection_resumable?
|
316
|
+
"#{key}:#{serial}:#{client_msg_serial}" if connection_resumable?
|
307
317
|
end
|
308
318
|
|
309
319
|
# Following a new connection being made, the connection ID, connection key
|
310
|
-
# and
|
320
|
+
# and connection serial need to match the details provided by the server.
|
311
321
|
#
|
312
322
|
# @return [void]
|
313
323
|
# @api private
|
314
324
|
def configure_new(connection_id, connection_key, connection_serial)
|
315
325
|
@id = connection_id
|
316
326
|
@key = connection_key
|
317
|
-
@client_serial = connection_serial
|
318
327
|
|
319
328
|
update_connection_serial connection_serial
|
320
329
|
end
|
@@ -542,11 +551,11 @@ module Ably
|
|
542
551
|
defaults.fetch(:realtime_request_timeout)
|
543
552
|
end
|
544
553
|
|
545
|
-
# Resets the client serial (msgSerial) sent to Ably for each new {Ably::Models::ProtocolMessage}
|
546
|
-
# (see #
|
554
|
+
# Resets the client message serial (msgSerial) sent to Ably for each new {Ably::Models::ProtocolMessage}
|
555
|
+
# (see #client_msg_serial)
|
547
556
|
# @api private
|
548
|
-
def
|
549
|
-
@
|
557
|
+
def reset_client_msg_serial
|
558
|
+
@client_msg_serial = -1
|
550
559
|
end
|
551
560
|
|
552
561
|
# When a hearbeat or any other message from Ably is received
|
@@ -568,15 +577,15 @@ module Ably
|
|
568
577
|
|
569
578
|
private
|
570
579
|
|
571
|
-
# The client serial is incremented for every message that is published that requires an ACK.
|
580
|
+
# The client message serial (msgSerial) is incremented for every message that is published that requires an ACK.
|
572
581
|
# Note that this is different to the connection serial that contains the last known serial number
|
573
582
|
# received from the server.
|
574
583
|
#
|
575
584
|
# A message serial number does not guarantee a message has been received, only sent.
|
576
585
|
# A connection serial guarantees the server has received the message and is thus used for connection recovery and resumes.
|
577
586
|
# @return [Integer] starting at -1 indicating no messages sent, 0 when the first message is sent
|
578
|
-
def
|
579
|
-
@
|
587
|
+
def client_msg_serial
|
588
|
+
@client_msg_serial
|
580
589
|
end
|
581
590
|
|
582
591
|
def resume_callbacks
|
@@ -601,11 +610,11 @@ module Ably
|
|
601
610
|
end
|
602
611
|
|
603
612
|
def add_message_serial_to(protocol_message)
|
604
|
-
@
|
605
|
-
protocol_message[:msgSerial] =
|
613
|
+
@client_msg_serial += 1
|
614
|
+
protocol_message[:msgSerial] = client_msg_serial
|
606
615
|
yield
|
607
616
|
rescue StandardError => e
|
608
|
-
@
|
617
|
+
@client_msg_serial -= 1
|
609
618
|
raise e
|
610
619
|
end
|
611
620
|
|
@@ -100,13 +100,11 @@ module Ably::Realtime
|
|
100
100
|
resend_pending_message_ack_queue
|
101
101
|
else
|
102
102
|
logger.debug { "ConnectionManager: Connection was not resumed, old connection ID #{connection.id} has been updated with new connection ID #{protocol_message.connection_id} and key #{protocol_message.connection_key}" }
|
103
|
-
connection.reset_client_serial
|
104
103
|
nack_messages_on_all_channels protocol_message.error
|
105
104
|
force_reattach_on_channels protocol_message.error
|
106
105
|
end
|
107
106
|
else
|
108
107
|
logger.debug { "ConnectionManager: New connection created with ID #{protocol_message.connection_id} and key #{protocol_message.connection_key}" }
|
109
|
-
connection.reset_client_serial
|
110
108
|
end
|
111
109
|
|
112
110
|
reattach_suspended_channels protocol_message.error
|
data/lib/ably/version.rb
CHANGED
@@ -661,17 +661,19 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
661
661
|
client.connection.once(:disconnected) { raise 'Upgrade does not require a disconnect' }
|
662
662
|
|
663
663
|
channel = client.channels.get('foo')
|
664
|
-
channel.
|
665
|
-
|
666
|
-
|
664
|
+
channel.attach do
|
665
|
+
channel.publish('not-allowed').errback do |error|
|
666
|
+
expect(error.code).to eql(40160)
|
667
|
+
expect(error.message).to match(/permission denied/)
|
667
668
|
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
669
|
+
client.auth.authorize(nil, auth_callback: upgraded_token_cb)
|
670
|
+
client.connection.once(:update) do
|
671
|
+
expect(client.connection.error_reason).to be_nil
|
672
|
+
channel.subscribe('now-allowed') do |message|
|
673
|
+
stop_reactor
|
674
|
+
end
|
675
|
+
channel.publish 'now-allowed'
|
673
676
|
end
|
674
|
-
channel.publish 'now-allowed'
|
675
677
|
end
|
676
678
|
end
|
677
679
|
end
|
@@ -112,22 +112,26 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
112
112
|
|
113
113
|
context 'in multiple ProtocolMessages', em_timeout: (30 / 10) + 5 do
|
114
114
|
it 'retrieves limited history forwards with pagination' do
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
115
|
+
channel.attach do
|
116
|
+
messages_sent.times do |index|
|
117
|
+
EventMachine.add_timer(index.to_f / rate_per_second) do
|
118
|
+
channel.publish('event', "history#{index}") do
|
119
|
+
next unless index == messages_sent - 1
|
120
|
+
ensure_message_history_direction_and_paging_is_correct :forwards
|
121
|
+
end
|
120
122
|
end
|
121
123
|
end
|
122
124
|
end
|
123
125
|
end
|
124
126
|
|
125
127
|
it 'retrieves limited history backwards with pagination' do
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
channel.attach do
|
129
|
+
messages_sent.times.to_a.reverse.each do |index|
|
130
|
+
EventMachine.add_timer((messages_sent - index).to_f / rate_per_second) do
|
131
|
+
channel.publish('event', "history#{index}") do
|
132
|
+
next unless index == 0
|
133
|
+
ensure_message_history_direction_and_paging_is_correct :backwards if index == 0
|
134
|
+
end
|
131
135
|
end
|
132
136
|
end
|
133
137
|
end
|
@@ -139,18 +143,20 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
139
143
|
let(:messages_per_batch) { 10 }
|
140
144
|
|
141
145
|
it 'return the same results with unique matching message IDs' do
|
142
|
-
|
143
|
-
|
144
|
-
|
146
|
+
channel.attach do
|
147
|
+
batches.times do |batch|
|
148
|
+
EventMachine.add_timer(batch.to_f / batches.to_f) do
|
149
|
+
messages_per_batch.times { |index| channel.publish('event') }
|
150
|
+
end
|
145
151
|
end
|
146
|
-
end
|
147
152
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
153
|
+
channel.subscribe('event') do |message|
|
154
|
+
messages << message
|
155
|
+
if messages.count == batches * messages_per_batch
|
156
|
+
channel.history do |page|
|
157
|
+
expect(page.items.map(&:id).sort).to eql(messages.map(&:id).sort)
|
158
|
+
stop_reactor
|
159
|
+
end
|
154
160
|
end
|
155
161
|
end
|
156
162
|
end
|
@@ -921,7 +921,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
921
921
|
end
|
922
922
|
end
|
923
923
|
|
924
|
-
it 'retains the
|
924
|
+
it 'retains the client_msg_serial (#RTN15c2, #RTN15c3)' do
|
925
925
|
last_message = nil
|
926
926
|
channel = client.channels.get("foo")
|
927
927
|
|
@@ -1103,7 +1103,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
1103
1103
|
end
|
1104
1104
|
end
|
1105
1105
|
|
1106
|
-
it '
|
1106
|
+
it 'continues to use the client_msg_serial (#RTN15c3)' do
|
1107
1107
|
last_message = nil
|
1108
1108
|
channel = client.channels.get("foo")
|
1109
1109
|
|
@@ -1121,7 +1121,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
1121
1121
|
connection.once(:connected) do
|
1122
1122
|
channel.publish("first on new connection") do
|
1123
1123
|
# Message serial reset after failed resume
|
1124
|
-
expect(last_message.message_serial).to eql(
|
1124
|
+
expect(last_message.message_serial).to eql(2)
|
1125
1125
|
stop_reactor
|
1126
1126
|
end
|
1127
1127
|
end
|
@@ -264,7 +264,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
264
264
|
channel.subscribe('event') do |message|
|
265
265
|
messages_received << message.data.to_i
|
266
266
|
if messages_received.count == total_expected
|
267
|
-
expect(messages_received).to match(total_expected.times)
|
267
|
+
expect(messages_received).to match(total_expected.times.to_a)
|
268
268
|
expect(auth_requests.count).to eql(iteration + 1)
|
269
269
|
EventMachine.add_timer(1) do
|
270
270
|
channel.unsubscribe 'event'
|
@@ -649,16 +649,47 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
649
649
|
end
|
650
650
|
|
651
651
|
it 'is set to 1 when the second message is received' do
|
652
|
-
channel.
|
653
|
-
|
652
|
+
channel.attach do
|
653
|
+
messages = []
|
654
|
+
channel.subscribe do |message|
|
655
|
+
messages << message
|
656
|
+
if messages.length == 2
|
657
|
+
expect(connection.serial).to eql(1)
|
658
|
+
stop_reactor
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
channel.publish('event', 'data') do
|
663
|
+
channel.publish('event', 'data')
|
664
|
+
end
|
654
665
|
end
|
666
|
+
end
|
667
|
+
end
|
655
668
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
669
|
+
describe '#msgSerial' do
|
670
|
+
context 'when messages are queued for publish before a connection is established' do
|
671
|
+
let(:batches) { 6 }
|
672
|
+
let(:messages_per_batch) { 10 }
|
673
|
+
|
674
|
+
let(:publishing_client) { auto_close Ably::Realtime::Client.new(default_options) }
|
675
|
+
let(:channel_name) { random_str }
|
676
|
+
let(:publishing_channel) { publishing_client.channels.get(channel_name) }
|
677
|
+
let(:receiving_channel) { client.channels.get(channel_name) }
|
678
|
+
|
679
|
+
it 'the msgSerial is always incrementing (and not reset when the new connection is established) ensuring messages are never de-duped by the realtime service' do
|
680
|
+
messages = []
|
681
|
+
|
682
|
+
receiving_channel.attach do
|
683
|
+
receiving_channel.subscribe('event') do |message|
|
684
|
+
messages << message
|
685
|
+
stop_reactor if messages.count == batches * messages_per_batch
|
686
|
+
end
|
687
|
+
|
688
|
+
batches.times do |batch|
|
689
|
+
EventMachine.add_timer(batch.to_f / batches.to_f) do
|
690
|
+
messages_per_batch.times { |index| publishing_channel.publish('event') }
|
691
|
+
end
|
692
|
+
end
|
662
693
|
end
|
663
694
|
end
|
664
695
|
end
|
@@ -1005,10 +1036,9 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1005
1036
|
let(:client_options) { default_options.merge(websocket_heartbeats_disabled: true) }
|
1006
1037
|
|
1007
1038
|
it 'does not provide the heartbeats argument in the websocket connection params (#RTN23b)' do
|
1008
|
-
skip 'Native heartbeats not yet supported in the WS driver https://github.com/ably/ably-ruby/issues/116'
|
1009
1039
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1010
1040
|
uri = URI.parse(url)
|
1011
|
-
expect(CGI::parse(uri.query)['heartbeats'][0]).to
|
1041
|
+
expect(CGI::parse(uri.query)['heartbeats'][0]).to eql('true')
|
1012
1042
|
stop_reactor
|
1013
1043
|
end
|
1014
1044
|
client
|
@@ -1126,7 +1156,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1126
1156
|
expected_serial += 1 # attach message received
|
1127
1157
|
expect(connection.serial).to eql(expected_serial)
|
1128
1158
|
|
1129
|
-
expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}")
|
1159
|
+
expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}:#{connection.send(:client_msg_serial)}")
|
1130
1160
|
stop_reactor
|
1131
1161
|
end
|
1132
1162
|
end
|
@@ -1237,6 +1267,78 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1237
1267
|
end
|
1238
1268
|
end
|
1239
1269
|
end
|
1270
|
+
|
1271
|
+
context 'when messages have been published' do
|
1272
|
+
describe 'the new connection' do
|
1273
|
+
it 'uses the correct msgSerial from the old connection' do
|
1274
|
+
msg_serial, recovery_key, connection_id = nil, nil, nil
|
1275
|
+
|
1276
|
+
channel.attach do
|
1277
|
+
expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
|
1278
|
+
connection_id = client.connection.id
|
1279
|
+
connection.transport.__incoming_protocol_msgbus__
|
1280
|
+
channel.publish('event', 'message') do
|
1281
|
+
msg_serial = connection.send(:client_msg_serial)
|
1282
|
+
expect(msg_serial).to eql(0)
|
1283
|
+
recovery_key = client.connection.recovery_key
|
1284
|
+
connection.transition_state_machine! :failed
|
1285
|
+
end
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
connection.on(:failed) do
|
1289
|
+
recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
|
1290
|
+
recover_client_channel = recover_client.channel(channel_name)
|
1291
|
+
recover_client_channel.attach do
|
1292
|
+
expect(recover_client.connection.id).to eql(connection_id)
|
1293
|
+
expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
|
1294
|
+
stop_reactor
|
1295
|
+
end
|
1296
|
+
end
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
end
|
1300
|
+
|
1301
|
+
context 'when messages are published before the new connection is recovered' do
|
1302
|
+
describe 'the new connection' do
|
1303
|
+
it 'uses the correct msgSerial from the old connection for the queued messages' do
|
1304
|
+
msg_serial, recovery_key, connection_id = nil, nil, nil
|
1305
|
+
|
1306
|
+
channel.attach do
|
1307
|
+
expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
|
1308
|
+
connection_id = client.connection.id
|
1309
|
+
connection.transport.__incoming_protocol_msgbus__
|
1310
|
+
channel.publish('event', 'message-1') do
|
1311
|
+
msg_serial = connection.send(:client_msg_serial)
|
1312
|
+
expect(msg_serial).to eql(0)
|
1313
|
+
recovery_key = client.connection.recovery_key
|
1314
|
+
connection.transition_state_machine! :failed
|
1315
|
+
end
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
connection.on(:failed) do
|
1319
|
+
recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
|
1320
|
+
recover_client_channel = recover_client.channel(channel_name)
|
1321
|
+
expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
|
1322
|
+
|
1323
|
+
recover_client.connection.once(:connecting) do
|
1324
|
+
recover_client_channel.publish('event', 'message-2')
|
1325
|
+
expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial + 1)
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
recover_client_channel.attach do
|
1329
|
+
expect(recover_client.connection.id).to eql(connection_id)
|
1330
|
+
|
1331
|
+
recover_client_channel.subscribe do |message|
|
1332
|
+
raise "Unexpected message #{message}" if message.data != 'message-2'
|
1333
|
+
EventMachine.add_timer(2) do
|
1334
|
+
stop_reactor
|
1335
|
+
end
|
1336
|
+
end
|
1337
|
+
end
|
1338
|
+
end
|
1339
|
+
end
|
1340
|
+
end
|
1341
|
+
end
|
1240
1342
|
end
|
1241
1343
|
|
1242
1344
|
context 'with :recover option' do
|
@@ -1250,7 +1352,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1250
1352
|
end
|
1251
1353
|
|
1252
1354
|
context 'with invalid formatted value sent to server' do
|
1253
|
-
let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1', log_level: :none) }
|
1355
|
+
let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1:0', log_level: :none) }
|
1254
1356
|
|
1255
1357
|
it 'sets the #error_reason and moves the connection to FAILED' do
|
1256
1358
|
connection.once(:failed) do |state_change|
|
@@ -1265,7 +1367,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1265
1367
|
end
|
1266
1368
|
|
1267
1369
|
context 'with expired (missing) value sent to server' do
|
1268
|
-
let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0', log_level: :fatal) }
|
1370
|
+
let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0:0', log_level: :fatal) }
|
1269
1371
|
|
1270
1372
|
it 'connects but sets the error reason and includes the reason in the state change' do
|
1271
1373
|
connection.once(:connected) do |state_change|
|