ably 1.0.5 → 1.0.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -1
  3. data/ably.gemspec +4 -3
  4. data/lib/ably/auth.rb +4 -4
  5. data/lib/ably/logger.rb +1 -1
  6. data/lib/ably/models/idiomatic_ruby_wrapper.rb +8 -8
  7. data/lib/ably/models/message.rb +6 -4
  8. data/lib/ably/models/presence_message.rb +6 -4
  9. data/lib/ably/modules/async_wrapper.rb +2 -2
  10. data/lib/ably/modules/conversions.rb +1 -1
  11. data/lib/ably/modules/encodeable.rb +1 -1
  12. data/lib/ably/modules/event_emitter.rb +2 -2
  13. data/lib/ably/modules/safe_deferrable.rb +1 -1
  14. data/lib/ably/modules/safe_yield.rb +1 -1
  15. data/lib/ably/modules/state_emitter.rb +5 -5
  16. data/lib/ably/realtime/auth.rb +1 -1
  17. data/lib/ably/realtime/channel.rb +3 -3
  18. data/lib/ably/realtime/channel/channel_manager.rb +2 -2
  19. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +3 -2
  20. data/lib/ably/realtime/connection.rb +11 -6
  21. data/lib/ably/realtime/connection/websocket_transport.rb +1 -1
  22. data/lib/ably/realtime/presence.rb +3 -3
  23. data/lib/ably/realtime/presence/members_map.rb +6 -6
  24. data/lib/ably/rest/channel.rb +2 -2
  25. data/lib/ably/rest/client.rb +20 -12
  26. data/lib/ably/version.rb +1 -1
  27. data/spec/acceptance/realtime/auth_spec.rb +13 -37
  28. data/spec/acceptance/realtime/channel_history_spec.rb +7 -1
  29. data/spec/acceptance/realtime/channel_spec.rb +3 -3
  30. data/spec/acceptance/realtime/client_spec.rb +2 -2
  31. data/spec/acceptance/realtime/connection_failures_spec.rb +221 -7
  32. data/spec/acceptance/realtime/connection_spec.rb +13 -21
  33. data/spec/acceptance/realtime/message_spec.rb +2 -2
  34. data/spec/acceptance/realtime/presence_history_spec.rb +12 -3
  35. data/spec/acceptance/realtime/presence_spec.rb +10 -10
  36. data/spec/acceptance/rest/auth_spec.rb +21 -48
  37. data/spec/acceptance/rest/client_spec.rb +193 -68
  38. data/spec/shared/client_initializer_behaviour.rb +1 -9
  39. data/spec/spec_helper.rb +2 -0
  40. data/spec/support/event_emitter_helper.rb +31 -0
  41. data/spec/support/event_machine_helper.rb +1 -1
  42. data/spec/support/test_logger_helper.rb +42 -0
  43. data/spec/unit/logger_spec.rb +1 -9
  44. data/spec/unit/modules/async_wrapper_spec.rb +2 -2
  45. data/spec/unit/modules/event_emitter_spec.rb +3 -3
  46. data/spec/unit/modules/state_emitter_spec.rb +10 -10
  47. data/spec/unit/realtime/channel_spec.rb +1 -1
  48. data/spec/unit/realtime/connection_spec.rb +1 -1
  49. data/spec/unit/realtime/presence_spec.rb +1 -1
  50. data/spec/unit/rest/channel_spec.rb +22 -0
  51. data/spec/unit/util/pub_sub_spec.rb +3 -3
  52. metadata +26 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a05adf2fb91ff543ae2797812dce8bc9c3119cc5ebf9c4a4468a177f07e2587c
4
- data.tar.gz: 97c229e631a871cdba553220677629bff959be160db9a864b8c5b712e26480d1
3
+ metadata.gz: adc7327c5853f3fe2fc8175a94877b4ffcbd22c24ce67cca48dfdce9464d3df1
4
+ data.tar.gz: e1740c98a0a6b24a67c8e3fcb6066a93902f9e12b17562a40c31d83184e86c75
5
5
  SHA512:
6
- metadata.gz: e3a2dc86d92459e6fe03721df934e819e504a39a6be899a42d3ea00b251e8dd8f465552e481451a024903ee199370a932addfdbda1962f441379fc5cb718ea73
7
- data.tar.gz: db1ca5e7ae13cb490f469d72a58ee7ca8f1377a834e200ade85045f0b341f411aaed966a4c7d2d85de9dd7cd55084a8369ff39505e76508ce744549723b305a8
6
+ metadata.gz: 4bee4e577b3c8598219d8143d193b3af8772ff95c25cb55694817ff08792b30ef365921d1cb99964673b58166cd2b08fc7a7931303342874b5412d0c19c46c20
7
+ data.tar.gz: 6aaea4c6281c4bc0d74b3262ed167698145dff798f1dcb735b7684792003117a7431944e4c2512cfcc6306b0fc98aea9f5d26d6132ad755afa1fca0a282a109c
@@ -1,11 +1,36 @@
1
1
  # Change Log
2
2
 
3
- ## [v1.0.5](https://github.com/ably/ably-ruby/tree/v1.0.5)
3
+ ## [v1.0.6](https://github.com/ably/ably-ruby/tree/v1.0.6)
4
4
 
5
+ [Full Changelog](https://github.com/ably/ably-ruby/compare/v1.0.5...v1.0.6)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - WebSocket driver does not emit events for heartbeats [\#116](https://github.com/ably/ably-ruby/issues/116)
10
+
11
+ **Closed issues:**
12
+
13
+ - Passing a frozen channel name or name gives an error on the REST client \[Reopen\] [\#145](https://github.com/ably/ably-ruby/issues/145)
14
+ - Passing a frozen channel name or name gives an error on the REST client [\#132](https://github.com/ably/ably-ruby/issues/132)
15
+
16
+ **Merged pull requests:**
17
+
18
+ - Add request id fix for bulk publishes [\#154](https://github.com/ably/ably-ruby/pull/154) ([mattheworiordan](https://github.com/mattheworiordan))
19
+ - Fix race condition in EventMachine [\#153](https://github.com/ably/ably-ruby/pull/153) ([mattheworiordan](https://github.com/mattheworiordan))
20
+ - Add support for WebSocket native heartbeats [\#151](https://github.com/ably/ably-ruby/pull/151) ([mattheworiordan](https://github.com/mattheworiordan))
21
+ - RSC15d test fixes; add \(failing\) tests for GET as well as POST [\#148](https://github.com/ably/ably-ruby/pull/148) ([SimonWoolf](https://github.com/SimonWoolf))
22
+ - Do not encode strings in-place [\#147](https://github.com/ably/ably-ruby/pull/147) ([mattheworiordan](https://github.com/mattheworiordan))
23
+ - Only resume if connection is fresh \(RTN15g\*\) [\#146](https://github.com/ably/ably-ruby/pull/146) ([mattheworiordan](https://github.com/mattheworiordan))
24
+ - Fix channel history pagination test [\#143](https://github.com/ably/ably-ruby/pull/143) ([funkyboy](https://github.com/funkyboy))
25
+ - Fix presence history test [\#141](https://github.com/ably/ably-ruby/pull/141) ([funkyboy](https://github.com/funkyboy))
26
+ - Do not encode strings in-place [\#140](https://github.com/ably/ably-ruby/pull/140) ([aschuster3](https://github.com/aschuster3))
27
+
28
+ ## [v1.0.5](https://github.com/ably/ably-ruby/tree/v1.0.5) (2018-04-23)
5
29
  [Full Changelog](https://github.com/ably/ably-ruby/compare/v1.0.4...v1.0.5)
6
30
 
7
31
  **Implemented enhancements:**
8
32
 
33
+ - Add Ruby 2.1 and 2.3 to Travis tests [\#129](https://github.com/ably/ably-ruby/issues/129)
9
34
  - Add supported platforms to README file [\#128](https://github.com/ably/ably-ruby/issues/128)
10
35
  - Add Ruby 2.1 and 2.3 to Travis tests [\#130](https://github.com/ably/ably-ruby/pull/130) ([funkyboy](https://github.com/funkyboy))
11
36
 
@@ -18,17 +18,18 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_runtime_dependency 'eventmachine', '~> 1.0'
21
+ spec.add_runtime_dependency 'eventmachine', '~> 1.2.6'
22
22
  spec.add_runtime_dependency 'em-http-request', '~> 1.1'
23
23
  spec.add_runtime_dependency 'statesman', '~> 1.0.0'
24
- spec.add_runtime_dependency 'faraday', '~> 0.9'
24
+ spec.add_runtime_dependency 'faraday', '~> 0.12'
25
+ spec.add_runtime_dependency 'excon', '~> 0.55'
25
26
 
26
27
  if RUBY_VERSION.match(/^1/)
27
28
  spec.add_runtime_dependency 'json', '< 2.0'
28
29
  else
29
30
  spec.add_runtime_dependency 'json'
30
31
  end
31
- spec.add_runtime_dependency 'websocket-driver', '~> 0.6'
32
+ spec.add_runtime_dependency 'websocket-driver', '~> 0.7'
32
33
  spec.add_runtime_dependency 'msgpack', '>= 0.6.2'
33
34
  spec.add_runtime_dependency 'addressable', '>= 2.0.0'
34
35
 
@@ -82,7 +82,7 @@ module Ably
82
82
 
83
83
  if has_client_id? && !token_creatable_externally? && !token_option
84
84
  raise ArgumentError, 'client_id cannot be provided without a complete API key or means to authenticate. An API key is needed to automatically authenticate with Ably and obtain a token' unless api_key_present?
85
- ensure_utf_8 :client_id, client_id
85
+ @client_id = ensure_utf_8(:client_id, client_id) if client_id
86
86
  end
87
87
 
88
88
  # If a token details object or token string is provided in the initializer
@@ -119,7 +119,7 @@ module Ably
119
119
  # token_details = client.auth.authorize
120
120
  #
121
121
  # # will use token request from block to authorize if not already authorized
122
- # token_details = client.auth.authorize {}, auth_callback: Proc.new do
122
+ # token_details = client.auth.authorize {}, auth_callback: lambda do |token_parmas|
123
123
  # # create token_request object
124
124
  # token_request
125
125
  # end
@@ -207,7 +207,7 @@ module Ably
207
207
  # client.auth.request_token ttl: 1.hour
208
208
  #
209
209
  # # token request using auth block
210
- # token_details = client.auth.request_token {}, auth_callback: Proc.new do
210
+ # token_details = client.auth.request_token {}, auth_callback: lambda do |token_params|
211
211
  # # create token_request object
212
212
  # token_request
213
213
  # end
@@ -633,7 +633,7 @@ module Ably
633
633
  method = auth_options[:auth_method] || options[:auth_method] || :get
634
634
  params = (auth_options[:auth_params] || options[:auth_method] || {}).merge(token_params)
635
635
 
636
- response = connection.send(method) do |request|
636
+ response = connection.public_send(method) do |request|
637
637
  request.url uri.path
638
638
  request.headers = auth_options[:auth_headers] || {}
639
639
  if method.to_s.downcase == 'post'
@@ -82,7 +82,7 @@ module Ably
82
82
 
83
83
  def default_logger
84
84
  ::Logger.new(STDOUT).tap do |logger|
85
- logger.formatter = proc do |severity, datetime, progname, msg|
85
+ logger.formatter = lambda do |severity, datetime, progname, msg|
86
86
  severity = ::Logger::SEV_LABEL.index(severity) if severity.kind_of?(String)
87
87
 
88
88
  formatted_date = if severity == ::Logger::DEBUG
@@ -210,14 +210,14 @@ module Ably::Models
210
210
  # key is not found in mixedCase.
211
211
  def source_key_for(symbolized_key)
212
212
  format_preferences = [
213
- proc { |key_sym| convert_to_mixed_case(key_sym) },
214
- proc { |key_sym| key_sym.to_sym },
215
- proc { |key_sym| key_sym.to_s },
216
- proc { |key_sym| convert_to_mixed_case(key_sym).to_sym },
217
- proc { |key_sym| convert_to_lower_case(key_sym) },
218
- proc { |key_sym| convert_to_lower_case(key_sym).to_sym },
219
- proc { |key_sym| convert_to_mixed_case(key_sym, force_camel: true) },
220
- proc { |key_sym| convert_to_mixed_case(key_sym, force_camel: true).to_sym }
213
+ lambda { |key_sym| convert_to_mixed_case(key_sym) },
214
+ lambda { |key_sym| key_sym.to_sym },
215
+ lambda { |key_sym| key_sym.to_s },
216
+ lambda { |key_sym| convert_to_mixed_case(key_sym).to_sym },
217
+ lambda { |key_sym| convert_to_lower_case(key_sym) },
218
+ lambda { |key_sym| convert_to_lower_case(key_sym).to_sym },
219
+ lambda { |key_sym| convert_to_mixed_case(key_sym, force_camel: true) },
220
+ lambda { |key_sym| convert_to_mixed_case(key_sym, force_camel: true).to_sym }
221
221
  ]
222
222
 
223
223
  preferred_format = format_preferences.detect do |format|
@@ -62,9 +62,11 @@ module Ably::Models
62
62
 
63
63
  set_attributes_object attributes
64
64
 
65
- ensure_utf_8 :name, name, allow_nil: true
66
- ensure_utf_8 :client_id, client_id, allow_nil: true
67
- ensure_utf_8 :encoding, encoding, allow_nil: true
65
+ self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
66
+ self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
67
+ self.attributes[:encoding] = ensure_utf_8(:encoding, encoding, allow_nil: true) if encoding
68
+
69
+ self.attributes.freeze
68
70
  end
69
71
 
70
72
  %w( name client_id encoding ).each do |attribute|
@@ -145,7 +147,7 @@ module Ably::Models
145
147
  end
146
148
 
147
149
  def set_attributes_object(new_attributes)
148
- @attributes = IdiomaticRubyWrapper(new_attributes.clone.freeze, stop_at: [:data, :extras])
150
+ @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
149
151
  end
150
152
 
151
153
  def logger
@@ -69,9 +69,11 @@ module Ably::Models
69
69
 
70
70
  set_attributes_object attributes
71
71
 
72
- ensure_utf_8 :client_id, client_id, allow_nil: true
73
- ensure_utf_8 :connection_id, connection_id, allow_nil: true
74
- ensure_utf_8 :encoding, encoding, allow_nil: true
72
+ self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
73
+ self.attributes[:connection_id] = ensure_utf_8(:connection_id, connection_id, allow_nil: true) if connection_id
74
+ self.attributes[:encoding] = ensure_utf_8(:encoding, encoding, allow_nil: true) if encoding
75
+
76
+ self.attributes.freeze
75
77
  end
76
78
 
77
79
  %w( client_id data encoding ).each do |attribute|
@@ -167,7 +169,7 @@ module Ably::Models
167
169
  end
168
170
 
169
171
  def set_attributes_object(new_attributes)
170
- @attributes = IdiomaticRubyWrapper(new_attributes.clone.freeze, stop_at: [:data])
172
+ @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data])
171
173
  end
172
174
 
173
175
  def logger
@@ -44,7 +44,7 @@ module Ably::Modules
44
44
  Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
45
45
  deferrable.callback(&success_callback) if success_callback
46
46
 
47
- operation_with_exception_handling = proc do
47
+ operation_with_exception_handling = lambda do
48
48
  begin
49
49
  yield
50
50
  rescue StandardError => err
@@ -57,7 +57,7 @@ module Ably::Modules
57
57
  end
58
58
  end
59
59
 
60
- complete_callback = proc do |result|
60
+ complete_callback = lambda do |result|
61
61
  deferrable.succeed result
62
62
  end
63
63
 
@@ -96,7 +96,7 @@ module Ably::Modules
96
96
  unless options[:allow_nil] && string_value.nil?
97
97
  raise ArgumentError, "#{field_name} must be a String" unless string_value.kind_of?(String)
98
98
  end
99
- string_value.encode!(Encoding::UTF_8) if string_value
99
+ string_value.encode(Encoding::UTF_8) if string_value
100
100
  rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError => e
101
101
  raise ArgumentError, "#{field_name} could not be converted to UTF-8: #{e.message}"
102
102
  end
@@ -95,7 +95,7 @@ module Ably::Modules
95
95
 
96
96
  previous_encoding = message_attributes[:encoding]
97
97
  encoders.each do |encoder|
98
- encoder.send method, message_attributes, channel_options
98
+ encoder.public_send method, message_attributes, channel_options
99
99
  end
100
100
  end until previous_encoding == message_attributes[:encoding]
101
101
 
@@ -31,7 +31,7 @@ module Ably
31
31
  # @option options [Proc] :coerce_into A lambda/Proc that is used to coerce the event names for all events. This is useful to ensure the event names conform to a naming or type convention.
32
32
  #
33
33
  # @example
34
- # configure_event_emitter coerce_into: Proc.new { |event| event.to_sym }
34
+ # configure_event_emitter coerce_into: lambda { |event| event.to_sym }
35
35
  #
36
36
  def configure_event_emitter(options = {})
37
37
  @event_emitter_coerce_proc = options[:coerce_into]
@@ -158,7 +158,7 @@ module Ably
158
158
  # #emit automatically deletes any blocks that return true thus allowing a block to be run once
159
159
  def proc_for_block(block, options = {})
160
160
  {
161
- emit_proc: Proc.new do |*args|
161
+ emit_proc: lambda do |*args|
162
162
  block.call(*args)
163
163
  true if options[:delete_once_run]
164
164
  end,
@@ -71,7 +71,7 @@ module Ably::Modules
71
71
 
72
72
  def fallback_logger
73
73
  @fallback_logger ||= ::Logger.new(STDOUT).tap do |logger|
74
- logger.formatter = proc do |severity, datetime, progname, msg|
74
+ logger.formatter = lambda do |severity, datetime, progname, msg|
75
75
  [
76
76
  "#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")} #{::Logger::SEV_LABEL[severity]} #{msg}",
77
77
  "Warning: SafeDeferrable expects the method #logger to be defined in the class it is included in, the method was not found in #{self.class}"
@@ -29,7 +29,7 @@ module Ably::Modules
29
29
 
30
30
  def fallback_logger
31
31
  @fallback_logger ||= ::Logger.new(STDOUT).tap do |logger|
32
- logger.formatter = proc do |severity, datetime, progname, msg|
32
+ logger.formatter = lambda do |severity, datetime, progname, msg|
33
33
  [
34
34
  "#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")} #{::Logger::SEV_LABEL[severity]} #{msg}",
35
35
  "Warning: SafeYield expects the method #logger to be defined in the class it is included in, the method was not found in #{self.class}"
@@ -81,13 +81,13 @@ module Ably::Modules
81
81
  failure_block = options.fetch(:else, nil)
82
82
  failure_wrapper = nil
83
83
 
84
- success_wrapper = Proc.new do
84
+ success_wrapper = lambda do |*args|
85
85
  yield
86
86
  off(&success_wrapper)
87
87
  off(&failure_wrapper) if failure_wrapper
88
88
  end
89
89
 
90
- failure_wrapper = proc do |*args|
90
+ failure_wrapper = lambda do |*args|
91
91
  failure_block.call(*args)
92
92
  off(&success_wrapper)
93
93
  off(&failure_wrapper)
@@ -119,7 +119,7 @@ module Ably::Modules
119
119
  def once_state_changed(options = {}, &block)
120
120
  raise ArgumentError, 'Block required' unless block_given?
121
121
 
122
- once_block = proc do |*args|
122
+ once_block = lambda do |*args|
123
123
  off(*self.class::STATE.map, &once_block)
124
124
  yield(*args)
125
125
  end
@@ -142,7 +142,7 @@ module Ably::Modules
142
142
  #
143
143
  def deferrable_for_state_change_to(target_state)
144
144
  Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
145
- fail_proc = Proc.new do |state_change|
145
+ fail_proc = lambda do |state_change|
146
146
  deferrable.fail state_change.reason
147
147
  end
148
148
  once_or_if(target_state, else: fail_proc) do
@@ -153,7 +153,7 @@ module Ably::Modules
153
153
  end
154
154
 
155
155
  def self.included(klass)
156
- klass.configure_event_emitter coerce_into: Proc.new { |event|
156
+ klass.configure_event_emitter coerce_into: lambda { |event|
157
157
  # Special case allows EVENT instead of STATE to be emitted
158
158
  # Relies on the assumption that EVENT is a superset of STATE
159
159
  if klass.const_defined?(:EVENT)
@@ -233,7 +233,7 @@ module Ably
233
233
  # @yield [Hash] Auth params for a new Realtime connection
234
234
  #
235
235
  def auth_params(&success_callback)
236
- fail_callback = Proc.new do |error, deferrable|
236
+ fail_callback = lambda do |error, deferrable|
237
237
  logger.error { "Failed to authenticate: #{error}" }
238
238
  if error.kind_of?(Ably::Exceptions::BaseAblyException)
239
239
  # Use base exception if it exists carrying forward the status codes
@@ -93,7 +93,7 @@ module Ably
93
93
  # @option channel_options [Hash,Ably::Models::CipherParams] :cipher A hash of options or a {Ably::Models::CipherParams} to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of +:cipher+ options
94
94
  #
95
95
  def initialize(client, name, channel_options = {})
96
- ensure_utf_8 :name, name
96
+ name = ensure_utf_8(:name, name)
97
97
 
98
98
  update_options channel_options
99
99
  @client = client
@@ -159,7 +159,7 @@ module Ably
159
159
  messages = if name.kind_of?(Enumerable)
160
160
  name
161
161
  else
162
- ensure_utf_8 :name, name, allow_nil: true
162
+ name = ensure_utf_8(:name, name, allow_nil: true)
163
163
  ensure_supported_payload data
164
164
  [{ name: name, data: data }.merge(attributes)]
165
165
  end
@@ -291,7 +291,7 @@ module Ably
291
291
  # @api private
292
292
  def __incoming_msgbus__
293
293
  @__incoming_msgbus__ ||= Ably::Util::PubSub.new(
294
- coerce_into: Proc.new { |event| Ably::Models::ProtocolMessage::ACTION(event) }
294
+ coerce_into: lambda { |event| Ably::Models::ProtocolMessage::ACTION(event) }
295
295
  )
296
296
  end
297
297
 
@@ -98,7 +98,7 @@ module Ably::Realtime
98
98
  def fail_messages_awaiting_ack(error, options = {})
99
99
  immediately = options[:immediately] || false
100
100
 
101
- fail_proc = Proc.new do
101
+ fail_proc = lambda do
102
102
  error = Ably::Exceptions::MessageDeliveryFailed.new("Continuity of connection was lost so published messages awaiting ACK have failed") unless error
103
103
  fail_messages_in_queue connection.__pending_message_ack_queue__, error
104
104
  end
@@ -224,7 +224,7 @@ module Ably::Realtime
224
224
  @pending_state_change_timer = nil
225
225
  end
226
226
 
227
- resend_if_disconnected_and_connected = Proc.new do
227
+ resend_if_disconnected_and_connected = lambda do
228
228
  connection.unsafe_once(:disconnected) do
229
229
  next unless pending_state_change_timer
230
230
  connection.unsafe_once(:connected) do
@@ -56,6 +56,7 @@ module Ably::Realtime
56
56
  end
57
57
 
58
58
  update_connection_recovery_info protocol_message
59
+ connection.set_connection_confirmed_alive
59
60
 
60
61
  case protocol_message.action
61
62
  when ACTION.Heartbeat
@@ -75,8 +76,10 @@ module Ably::Realtime
75
76
  elsif connection.connected?
76
77
  logger.debug { "Updated CONNECTED ProtocolMessage received (whilst connected)" }
77
78
  process_connected_update_message protocol_message
79
+ connection.set_connection_confirmed_alive # Connection protocol messages can change liveness settings such as max_idle_interval
78
80
  else
79
81
  process_connected_message protocol_message
82
+ connection.set_connection_confirmed_alive # Connection protocol messages can change liveness settings such as max_idle_interval
80
83
  end
81
84
 
82
85
  when ACTION.Disconnect, ACTION.Disconnected
@@ -132,8 +135,6 @@ module Ably::Realtime
132
135
  error = Ably::Exceptions::ProtocolError.new("Protocol Message Action #{protocol_message.action} is unsupported by this MessageDispatcher", 400, 80013)
133
136
  logger.fatal error.message
134
137
  end
135
-
136
- connection.set_connection_confirmed_alive
137
138
  end
138
139
 
139
140
  def dispatch_channel_error(protocol_message)
@@ -235,7 +235,7 @@ module Ably
235
235
  ping_id = SecureRandom.hex(16)
236
236
  heartbeat_action = Ably::Models::ProtocolMessage::ACTION.Heartbeat
237
237
 
238
- wait_for_ping = Proc.new do |protocol_message|
238
+ wait_for_ping = lambda do |protocol_message|
239
239
  next if finished
240
240
  if protocol_message.action == heartbeat_action && protocol_message.id == ping_id
241
241
  finished = true
@@ -423,9 +423,12 @@ module Ably
423
423
  lib: client.rest_client.lib_version_id,
424
424
  )
425
425
 
426
- # Use native websocket heartbeats if possible
427
- # TODO: Fix once https://github.com/ably/ably-ruby/issues/116 is resolved
428
- url_params['heartbeats'] = 'true' # unless defaults.fetch(:websocket_heartbeats_disabled)
426
+ # Use native websocket heartbeats if possible, but allow Ably protocol heartbeats
427
+ url_params['heartbeats'] = if defaults.fetch(:websocket_heartbeats_disabled)
428
+ 'true'
429
+ else
430
+ 'false'
431
+ end
429
432
 
430
433
  url_params['clientId'] = client.auth.client_id if client.auth.has_client_id?
431
434
 
@@ -579,7 +582,7 @@ module Ably
579
582
 
580
583
  def create_pub_sub_message_bus
581
584
  Ably::Util::PubSub.new(
582
- coerce_into: Proc.new do |event|
585
+ coerce_into: lambda do |event|
583
586
  raise KeyError, "Expected :protocol_message, :#{event} is disallowed" unless event == :protocol_message
584
587
  :protocol_message
585
588
  end
@@ -615,8 +618,10 @@ module Ably
615
618
  def connection_state_available?
616
619
  return true if connected?
617
620
 
621
+ return false if time_since_connection_confirmed_alive? > connection_state_ttl + details.max_idle_interval
622
+
618
623
  connected_last = state_history.reverse.find { |connected| connected.fetch(:state) == :connected }
619
- if connected_last.nil? || (connected_last.fetch(:transitioned_at) < Time.now - connection_state_ttl)
624
+ if connected_last.nil?
620
625
  false
621
626
  else
622
627
  true
@@ -208,7 +208,7 @@ module Ably::Realtime
208
208
 
209
209
  def create_pub_sub_message_bus
210
210
  Ably::Util::PubSub.new(
211
- coerce_into: Proc.new do |event|
211
+ coerce_into: lambda do |event|
212
212
  raise KeyError, "Expected :protocol_message, :#{event} is disallowed" unless event == :protocol_message
213
213
  :protocol_message
214
214
  end