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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41a1cf12a01ccf1b9ecf3523790c45d77c08815d23d1cd3b23058dd456377a0b
4
- data.tar.gz: e5174d825c354bc813819c3e0a0ab7341c46b8e04864ac24575c475cd773ad54
3
+ metadata.gz: 26f56201f9faae28b9b74ef9223e8d50c049a25d065f80d8612ce0013da46783
4
+ data.tar.gz: f74af9b0f0178576e41094fccf80821983da0b896e6bd7667fe534abe0d096bb
5
5
  SHA512:
6
- metadata.gz: 8327568876690de6bbc5e95d3ce7759f7856b73d91e8726f5880291cb5a5579d962cd4b93b4d87b497d9e395a7971f515b926c2f54e220b1ba2667744bc891dd
7
- data.tar.gz: 13752c5b6f79067275b192a55d14019ace0781eb061844248faf56b878d9afd78229396e82c11d171851f5570164921d9729e3ca1560c297e179e556ba87ed2e
6
+ metadata.gz: 2a4c6c4006a176c01eacd9f38d9f11a61fb7f64880a764a663eca26e2ed2b7806203f972edf7cb5f0dec1034e6776d6b6dac459766ba920cc09ea156022640a9
7
+ data.tar.gz: 59d33ebc03521cf47449140715b5506dca17ac6b3708b914b6b0987d038c56667231086c8ff81c8d740d8a62c4474ac78c9839360b795e2d5c8f779ad972e3a5
@@ -5,11 +5,14 @@ env:
5
5
  language: ruby
6
6
  rvm:
7
7
  - 1.9.3
8
- - 2.0.0
9
8
  - 2.1.10
10
- - 2.2.0
11
- - 2.3.6
12
- - 2.4.4
9
+ - 2.2.10
10
+ - 2.3.8
11
+ - 2.5.5
12
+ - 2.6.0
13
+ - 2.6.1
14
+ - 2.6.2
15
+ - 2.6.3
13
16
  script: spec/run_parallel_tests
14
17
  notifications:
15
18
  slack:
@@ -1,7 +1,24 @@
1
1
  # Change Log
2
2
 
3
- ## [v1.1.0](https://github.com/ably/ably-ruby/tree/v1.1.0)
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.
@@ -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'
@@ -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>[\w!-]+):(?<connection_serial>\-?\w+)$/
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 message serial need to match the details provided by the server.
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 #client_serial)
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 reset_client_serial
549
- @client_serial = -1
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 client_serial
579
- @client_serial
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
- @client_serial += 1
605
- protocol_message[:msgSerial] = client_serial
613
+ @client_msg_serial += 1
614
+ protocol_message[:msgSerial] = client_msg_serial
606
615
  yield
607
616
  rescue StandardError => e
608
- @client_serial -= 1
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
@@ -1,5 +1,5 @@
1
1
  module Ably
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.1'
3
3
  PROTOCOL_VERSION = '1.1'
4
4
 
5
5
  # Allow a variant to be configured for all instances of this client library
@@ -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.publish('not-allowed').errback do |error|
665
- expect(error.code).to eql(40160)
666
- expect(error.message).to match(/permission denied/)
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
- client.auth.authorize(nil, auth_callback: upgraded_token_cb)
669
- client.connection.once(:update) do
670
- expect(client.connection.error_reason).to be_nil
671
- channel.subscribe('now-allowed') do |message|
672
- stop_reactor
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
- messages_sent.times do |index|
116
- EventMachine.add_timer(index.to_f / rate_per_second) do
117
- channel.publish('event', "history#{index}") do
118
- next unless index == messages_sent - 1
119
- ensure_message_history_direction_and_paging_is_correct :forwards
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
- messages_sent.times.to_a.reverse.each do |index|
127
- EventMachine.add_timer((messages_sent - index).to_f / rate_per_second) do
128
- channel.publish('event', "history#{index}") do
129
- next unless index == 0
130
- ensure_message_history_direction_and_paging_is_correct :backwards if index == 0
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
- batches.times do |batch|
143
- EventMachine.add_timer(batch.to_f / batches.to_f) do
144
- messages_per_batch.times { channel.publish('event', 'data') }
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
- channel.subscribe('event') do |message|
149
- messages << message
150
- if messages.count == batches * messages_per_batch
151
- channel.history do |page|
152
- expect(page.items.map(&:id).sort).to eql(messages.map(&:id).sort)
153
- stop_reactor
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 client_serial (#RTN15c2, #RTN15c3)' do
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 'resets the client_serial (#RTN15c3)' do
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(0)
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.publish('event', 'data') do
653
- channel.publish('event', 'data')
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
- messages = []
657
- channel.subscribe do |message|
658
- messages << message
659
- if messages.length == 2
660
- expect(connection.serial).to eql(1)
661
- stop_reactor
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 be_nil
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|