ably-rest 0.8.6 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/SPEC.md +1049 -1001
  3. data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
  4. data/lib/submodules/ably-ruby/LICENSE +2 -2
  5. data/lib/submodules/ably-ruby/README.md +81 -20
  6. data/lib/submodules/ably-ruby/SPEC.md +1209 -693
  7. data/lib/submodules/ably-ruby/ably.gemspec +4 -4
  8. data/lib/submodules/ably-ruby/lib/ably/auth.rb +13 -4
  9. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -1
  10. data/lib/submodules/ably-ruby/lib/ably/logger.rb +3 -1
  11. data/lib/submodules/ably-ruby/lib/ably/models/cipher_params.rb +114 -0
  12. data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +10 -7
  13. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +3 -3
  14. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +28 -21
  15. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +19 -17
  16. data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/cipher.rb +10 -9
  17. data/lib/submodules/ably-ruby/lib/ably/models/paginated_result.rb +27 -1
  18. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +20 -18
  19. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +26 -19
  20. data/lib/submodules/ably-ruby/lib/ably/models/{stat.rb → stats.rb} +21 -19
  21. data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +14 -12
  22. data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +16 -14
  23. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
  24. data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +11 -1
  25. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +10 -10
  26. data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +18 -2
  27. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +3 -3
  28. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +13 -5
  29. data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
  30. data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +2 -2
  31. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +8 -8
  32. data/lib/submodules/ably-ruby/lib/ably/modules/statesman_monkey_patch.rb +2 -2
  33. data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +4 -2
  34. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -2
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +7 -6
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +7 -1
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +7 -12
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -2
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +7 -1
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +19 -8
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +16 -9
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +12 -3
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +35 -64
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +23 -9
  46. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -10
  47. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +1 -1
  48. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +16 -4
  49. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +7 -5
  50. data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +50 -40
  51. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  52. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +4 -4
  53. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +2 -4
  54. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +46 -8
  55. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +20 -20
  56. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +7 -7
  57. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +114 -111
  58. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +9 -9
  59. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +5 -5
  60. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +1 -1
  61. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +1 -1
  62. data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +4 -4
  63. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +15 -15
  64. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +4 -4
  65. data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +7 -7
  66. data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +4 -4
  67. data/lib/submodules/ably-ruby/spec/unit/models/cipher_params_spec.rb +140 -0
  68. data/lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
  69. data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
  70. data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/json_spec.rb +24 -0
  71. data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +3 -3
  72. data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +20 -18
  73. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +2 -2
  74. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +6 -6
  75. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +4 -4
  76. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
  77. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +5 -5
  78. data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +50 -17
  79. metadata +5 -3
@@ -1,5 +1,6 @@
1
1
  require 'eventmachine'
2
2
  require 'websocket/driver'
3
+ require 'em-http-request'
3
4
 
4
5
  require 'ably/modules/event_emitter'
5
6
 
@@ -189,9 +189,13 @@ module Ably
189
189
  private
190
190
  # The synchronous Auth class instanced by the Rest client
191
191
  # @return [Ably::Auth]
192
- attr_reader :auth_sync
192
+ def auth_sync
193
+ @auth_sync
194
+ end
193
195
 
194
- attr_reader :client
196
+ def client
197
+ @client
198
+ end
195
199
  end
196
200
  end
197
201
  end
@@ -82,8 +82,7 @@ module Ably
82
82
  # @param client [Ably::Rest::Client]
83
83
  # @param name [String] The name of the channel
84
84
  # @param channel_options [Hash] Channel options, currently reserved for Encryption options
85
- # @option channel_options [Boolean] :encrypted setting this to true for this channel will encrypt & decrypt all messages automatically
86
- # @option channel_options [Hash] :cipher_params A hash of options to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of +cipher_params+ options
85
+ # @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
87
86
  #
88
87
  def initialize(client, name, channel_options = {})
89
88
  ensure_utf_8 :name, name
@@ -294,7 +293,9 @@ module Ably
294
293
  private :change_state
295
294
 
296
295
  private
297
- attr_reader :queue
296
+ def queue
297
+ @queue
298
+ end
298
299
 
299
300
  def setup_event_handlers
300
301
  __incoming_msgbus__.subscribe(:message) do |message|
@@ -323,7 +324,7 @@ module Ably
323
324
  end
324
325
  end
325
326
 
326
- queue.push *messages
327
+ queue.push(*messages)
327
328
 
328
329
  if attached?
329
330
  process_queue
@@ -385,8 +386,8 @@ module Ably
385
386
  end
386
387
 
387
388
  def create_message(message)
388
- Ably::Models::Message(message.dup).tap do |message|
389
- message.encode self
389
+ Ably::Models::Message(message.dup).tap do |msg|
390
+ msg.encode self
390
391
  end
391
392
  end
392
393
 
@@ -94,8 +94,14 @@ module Ably::Realtime
94
94
  end
95
95
 
96
96
  private
97
+ def channel
98
+ @channel
99
+ end
100
+
101
+ def connection
102
+ @connection
103
+ end
97
104
 
98
- attr_reader :channel, :connection
99
105
  def_delegators :channel, :can_transition_to?
100
106
 
101
107
  # If the connection has not previously connected, connect now
@@ -90,13 +90,13 @@ module Ably
90
90
  @auth = Ably::Realtime::Auth.new(self)
91
91
  @channels = Ably::Realtime::Channels.new(self)
92
92
  @connection = Ably::Realtime::Connection.new(self, options)
93
- @echo_messages = @rest_client.options.fetch(:echo_messages, true) == false ? false : true
94
- @queue_messages = @rest_client.options.fetch(:queue_messages, true) == false ? false : true
95
- @custom_realtime_host = @rest_client.options[:realtime_host] || @rest_client.options[:ws_host]
96
- @auto_connect = @rest_client.options.fetch(:auto_connect, true) == false ? false : true
97
- @recover = @rest_client.options[:recover]
93
+ @echo_messages = rest_client.options.fetch(:echo_messages, true) == false ? false : true
94
+ @queue_messages = rest_client.options.fetch(:queue_messages, true) == false ? false : true
95
+ @custom_realtime_host = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
96
+ @auto_connect = rest_client.options.fetch(:auto_connect, true) == false ? false : true
97
+ @recover = rest_client.options[:recover]
98
98
 
99
- raise ArgumentError, "Recovery key is invalid" if @recover && !@recover.match(Connection::RECOVER_REGEX)
99
+ raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
100
100
  end
101
101
 
102
102
  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
@@ -150,11 +150,6 @@ module Ably
150
150
  endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
151
151
  end
152
152
 
153
-
154
- def connection
155
- @connection
156
- end
157
-
158
153
  # (see Ably::Rest::Client#register_encoder)
159
154
  def register_encoder(encoder)
160
155
  rest_client.register_encoder encoder
@@ -176,7 +171,7 @@ module Ably
176
171
  # @return [URI::Generic] Fallback endpoint used to connect to the realtime Ably service. Note, after each connection attempt, a new random {Ably::FALLBACK_HOSTS fallback host} is used
177
172
  # @api private
178
173
  def fallback_endpoint
179
- unless @fallback_endpoints
174
+ unless defined?(@fallback_endpoints) && @fallback_endpoints
180
175
  @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
181
176
  end
182
177
 
@@ -13,7 +13,13 @@ module Ably::Realtime
13
13
  end
14
14
 
15
15
  private
16
- attr_reader :client, :connection
16
+ def client
17
+ @client
18
+ end
19
+
20
+ def connection
21
+ @connection
22
+ end
17
23
 
18
24
  def channels
19
25
  client.channels
@@ -144,6 +150,7 @@ module Ably::Realtime
144
150
  def process_connected_message(protocol_message)
145
151
  if client.auth.token_client_id_allowed?(protocol_message.connection_details.client_id)
146
152
  client.auth.configure_client_id protocol_message.connection_details.client_id
153
+ client.connection.set_connection_details protocol_message.connection_details
147
154
  connection.transition_state_machine :connected, reason: protocol_message.error, protocol_message: protocol_message
148
155
  else
149
156
  reason = Ably::Exceptions::IncompatibleClientId.new("Client ID '#{protocol_message.connection_details.client_id}' specified by the server is incompatible with the library's configured client ID '#{client.client_id}'", 400, 40012)
@@ -195,7 +202,7 @@ module Ably::Realtime
195
202
 
196
203
  def subscribe_to_incoming_protocol_messages
197
204
  connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |*args|
198
- dispatch_protocol_message *args
205
+ dispatch_protocol_message(*args)
199
206
  end
200
207
  end
201
208
  end
@@ -17,7 +17,13 @@ module Ably::Realtime
17
17
  end
18
18
 
19
19
  private
20
- attr_reader :client, :connection
20
+ def client
21
+ @client
22
+ end
23
+
24
+ def connection
25
+ @connection
26
+ end
21
27
 
22
28
  def can_send_messages?
23
29
  connection.connected? || connection.closing?
@@ -58,7 +58,7 @@ module Ably
58
58
  ensure_state_machine_emits 'Ably::Models::ConnectionStateChange'
59
59
 
60
60
  # Expected format for a connection recover key
61
- RECOVER_REGEX = /^(?<recover>[\w-]+):(?<connection_serial>\-?\w+)$/
61
+ RECOVER_REGEX = /^(?<recover>[\w!-]+):(?<connection_serial>\-?\w+)$/
62
62
 
63
63
  # Defaults for automatic connection recovery and timeouts
64
64
  DEFAULTS = {
@@ -84,6 +84,10 @@ module Ably
84
84
  # @return [Ably::Models::ErrorInfo,Ably::Exceptions::BaseAblyException]
85
85
  attr_reader :error_reason
86
86
 
87
+ # Connection details of the currently established connection
88
+ # @return [Ably::Models::ConnectionDetails]
89
+ attr_reader :details
90
+
87
91
  # {Ably::Realtime::Client} associated with this connection
88
92
  # @return [Ably::Realtime::Client]
89
93
  attr_reader :client
@@ -178,12 +182,12 @@ module Ably
178
182
 
179
183
  once(:connected) do
180
184
  deferrable.succeed
181
- off &fail_callback
185
+ off(&fail_callback)
182
186
  end
183
187
 
184
188
  once(:failed, :closed, :closing) do
185
189
  deferrable.fail
186
- off &succeed_callback
190
+ off(&succeed_callback)
187
191
  end
188
192
  end
189
193
  end
@@ -356,10 +360,10 @@ module Ably
356
360
  # @api private
357
361
  def send_protocol_message(protocol_message)
358
362
  add_message_serial_if_ack_required_to(protocol_message) do
359
- Ably::Models::ProtocolMessage.new(protocol_message, logger: logger).tap do |protocol_message|
360
- add_message_to_outgoing_queue protocol_message
361
- notify_message_dispatcher_of_new_message protocol_message
362
- logger.debug("Connection: Prot msg queued =>: #{protocol_message.action} #{protocol_message}")
363
+ Ably::Models::ProtocolMessage.new(protocol_message, logger: logger).tap do |message|
364
+ add_message_to_outgoing_queue message
365
+ notify_message_dispatcher_of_new_message message
366
+ logger.debug("Connection: Prot msg queued =>: #{message.action} #{message}")
363
367
  end
364
368
  end
365
369
  end
@@ -437,6 +441,11 @@ module Ably
437
441
  @error_reason = nil
438
442
  end
439
443
 
444
+ # @api private
445
+ def set_connection_details(connection_details)
446
+ @details = connection_details
447
+ end
448
+
440
449
  # Executes registered callbacks for a successful connection resume event
441
450
  # @api private
442
451
  def resumed
@@ -476,7 +485,9 @@ module Ably
476
485
  # A connection serial guarantees the server has received the message and is thus used for connection
477
486
  # recovery and resumes.
478
487
  # @return [Integer] starting at -1 indicating no messages sent, 0 when the first message is sent
479
- attr_reader :client_serial
488
+ def client_serial
489
+ @client_serial
490
+ end
480
491
 
481
492
  def resume_callbacks
482
493
  @resume_callbacks ||= []
@@ -1,3 +1,5 @@
1
+ require 'ably/rest/middleware/exceptions'
2
+
1
3
  module Ably::Realtime
2
4
  class Connection
3
5
  # ConnectionManager is responsible for all actions relating to underlying connection and transports,
@@ -10,12 +12,13 @@ module Ably::Realtime
10
12
  class ConnectionManager
11
13
  # Error codes from the server that can potentially be resolved
12
14
  RESOLVABLE_ERROR_CODES = {
13
- token_expired: 40140
15
+ token_expired: Ably::Rest::Middleware::Exceptions::TOKEN_EXPIRED_CODE
14
16
  }
15
17
 
16
18
  def initialize(connection)
17
- @connection = connection
18
- @timers = Hash.new { |hash, key| hash[key] = [] }
19
+ @connection = connection
20
+ @timers = Hash.new { |hash, key| hash[key] = [] }
21
+ @renewing_token = false
19
22
 
20
23
  connection.unsafe_on(:closed) do
21
24
  connection.reset_resume_info
@@ -58,7 +61,7 @@ module Ably::Realtime
58
61
  end
59
62
 
60
63
  logger.debug "ConnectionManager: Setting up automatic connection timeout timer for #{realtime_request_timeout}s"
61
- create_timeout_timer_whilst_in_state(:connect, realtime_request_timeout) do
64
+ create_timeout_timer_whilst_in_state(:connecting, realtime_request_timeout) do
62
65
  connection_opening_failed Ably::Exceptions::ConnectionTimeout.new("Connection to Ably timed out after #{realtime_request_timeout}s", nil, 80014)
63
66
  end
64
67
  end
@@ -123,7 +126,7 @@ module Ably::Realtime
123
126
  def close_connection
124
127
  connection.send_protocol_message(action: Ably::Models::ProtocolMessage::ACTION.Close)
125
128
 
126
- create_timeout_timer_whilst_in_state(:close, realtime_request_timeout) do
129
+ create_timeout_timer_whilst_in_state(:closing, realtime_request_timeout) do
127
130
  force_close_connection if connection.closing?
128
131
  end
129
132
  end
@@ -153,7 +156,7 @@ module Ably::Realtime
153
156
  return unless can_retry_connection? # do not always reattempt connection or change state as client may be re-authorising
154
157
 
155
158
  if error.kind_of?(Ably::Models::ErrorInfo)
156
- if error.code == RESOLVABLE_ERROR_CODES.fetch(:token_expired)
159
+ if RESOLVABLE_ERROR_CODES.fetch(:token_expired).include?(error.code)
157
160
  next_state = get_next_retry_state_info
158
161
  logger.debug "ConnectionManager: Transport disconnected because of token expiry, pausing #{next_state.fetch(:pause)}s before reattempting to connect"
159
162
  EventMachine.add_timer(next_state.fetch(:pause)) { renew_token_and_reconnect error }
@@ -181,7 +184,7 @@ module Ably::Realtime
181
184
  logger.debug "ConnectionManager: Transport disconnected whilst connection in #{connection.state} state"
182
185
  end
183
186
 
184
- if error.kind_of?(Ably::Models::ErrorInfo) && error.code != RESOLVABLE_ERROR_CODES.fetch(:token_expired)
187
+ if error.kind_of?(Ably::Models::ErrorInfo) && !RESOLVABLE_ERROR_CODES.fetch(:token_expired).include?(error.code)
185
188
  connection.emit :error, error
186
189
  logger.error "ConnectionManager: Error in Disconnected ProtocolMessage received from the server - #{error}"
187
190
  end
@@ -213,11 +216,15 @@ module Ably::Realtime
213
216
  end
214
217
 
215
218
  private
216
- attr_reader :connection
219
+ def connection
220
+ @connection
221
+ end
217
222
 
218
223
  # Timers used to manage connection state, for internal use by the client library
219
224
  # @return [Hash]
220
- attr_reader :timers
225
+ def timers
226
+ @timers
227
+ end
221
228
 
222
229
  def transport
223
230
  connection.transport
@@ -98,11 +98,20 @@ module Ably::Realtime
98
98
  end
99
99
 
100
100
  private
101
- attr_reader :connection, :driver, :reason_closed
101
+ def driver
102
+ @driver
103
+ end
104
+
105
+ def connection
106
+ @connection
107
+ end
108
+
109
+ def reason_closed
110
+ @reason_closed
111
+ end
102
112
 
103
113
  # Send object down the WebSocket driver connection as a serialized string/byte array based on protocol
104
114
  # @param [Object] object to serialize and send to the WebSocket driver
105
- # @api public
106
115
  def send_object(object)
107
116
  case client.protocol
108
117
  when :json
@@ -122,7 +131,7 @@ module Ably::Realtime
122
131
  end
123
132
 
124
133
  def clear_timer
125
- if @timer
134
+ if defined?(@timer) && @timer
126
135
  @timer.cancel
127
136
  @timer = nil
128
137
  end
@@ -59,26 +59,16 @@ module Ably::Realtime
59
59
  # Enter this client into this channel. This client will be added to the presence set
60
60
  # and presence subscribers will see an enter message for this client.
61
61
  #
62
- # @param [Hash] options an options Hash to specify client data and/or client ID
63
- # @option options [String] :data optional data (eg a status message) for this member
64
- # @option options [String] :client_id the optional id of the client.
65
- # This option is provided to support connections from server instances that act on behalf of
66
- # multiple client_ids. In order to be able to enter the channel with this method, the client
67
- # library must have been instanced either with a key, or with a token bound to the wildcard clientId.
62
+ # @param [String,Hash,nil] data optional data (eg a status message) for this member
68
63
  #
69
64
  # @yield [Ably::Realtime::Presence] On success, will call the block with this {Ably::Realtime::Presence} object
70
65
  # @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
71
66
  #
72
- def enter(options = {}, &success_block)
73
- client_id = options.fetch(:client_id, self.client_id)
74
- data = options.fetch(:data, nil)
67
+ def enter(data = nil, &success_block)
75
68
  deferrable = create_deferrable
76
69
 
77
- ensure_supported_client_id client_id
78
- ensure_supported_payload data unless data.nil?
79
-
70
+ ensure_supported_payload data
80
71
  @data = data
81
- @client_id = client_id
82
72
 
83
73
  return deferrable_succeed(deferrable, &success_block) if state == STATE.Entered
84
74
 
@@ -94,8 +84,8 @@ module Ably::Realtime
94
84
  Ably::Models::PresenceMessage::ACTION.Enter,
95
85
  deferrable: deferrable,
96
86
  target_state: STATE.Entered,
97
- client_id: client_id,
98
87
  data: data,
88
+ client_id: client_id,
99
89
  failed_state: STATE.Failed,
100
90
  &success_block
101
91
  )
@@ -111,36 +101,30 @@ module Ably::Realtime
111
101
  # either with a key, or with a token bound to the wildcard client_id
112
102
  #
113
103
  # @param [String] client_id id of the client
114
- #
115
- # @param [Hash] options an options Hash for this client event
116
- # @option options [String] :data optional data (eg a status message) for this member
104
+ # @param [String,Hash,nil] data optional data (eg a status message) for this member
117
105
  #
118
106
  # @yield [Ably::Realtime::Presence] On success, will call the block with this {Ably::Realtime::Presence} object
119
107
  # @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
120
108
  #
121
- def enter_client(client_id, options = {}, &success_block)
122
- raise ArgumentError, 'options must be a Hash' unless options.kind_of?(Hash)
109
+ def enter_client(client_id, data = nil, &success_block)
123
110
  ensure_supported_client_id client_id
124
- ensure_supported_payload options[:data] if options.has_key?(:data)
111
+ ensure_supported_payload data
125
112
 
126
- send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Enter, client_id, options, &success_block)
113
+ send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Enter, client_id, data, &success_block)
127
114
  end
128
115
 
129
116
  # Leave this client from this channel. This client will be removed from the presence
130
117
  # set and presence subscribers will see a leave message for this client.
131
118
  #
132
- # @param [Hash,String] options an options Hash to specify client data and/or client ID
133
- # @option options [String] :data optional data (eg a status message) for this member
119
+ # @param (see Presence#enter)
134
120
  #
135
121
  # @yield (see Presence#enter)
136
122
  # @return (see Presence#enter)
137
123
  #
138
- def leave(options = {}, &success_block)
139
- data = options.fetch(:data, self.data) # nil value defaults leave data to existing value
124
+ def leave(data = nil, &success_block)
140
125
  deferrable = create_deferrable
141
126
 
142
- ensure_supported_client_id client_id
143
- ensure_supported_payload data unless data.nil?
127
+ ensure_supported_payload data
144
128
  raise Ably::Exceptions::Standard.new('Unable to leave presence channel that is not entered', 400, 91002) unless able_to_leave?
145
129
 
146
130
  @data = data
@@ -159,8 +143,8 @@ module Ably::Realtime
159
143
  Ably::Models::PresenceMessage::ACTION.Leave,
160
144
  deferrable: deferrable,
161
145
  target_state: STATE.Left,
162
- client_id: client_id,
163
146
  data: data,
147
+ client_id: client_id,
164
148
  failed_state: STATE.Failed,
165
149
  &success_block
166
150
  )
@@ -172,35 +156,30 @@ module Ably::Realtime
172
156
  # presence set and presence subscribers will see a leave message for this client.
173
157
  #
174
158
  # @param (see Presence#enter_client)
175
- # @option options (see Presence#enter_client)
176
159
  #
177
160
  # @yield (see Presence#enter_client)
178
161
  # @return (see Presence#enter_client)
179
162
  #
180
- def leave_client(client_id, options = {}, &success_block)
181
- raise ArgumentError, 'options must be a Hash' unless options.kind_of?(Hash)
163
+ def leave_client(client_id, data = nil, &success_block)
182
164
  ensure_supported_client_id client_id
183
- ensure_supported_payload options[:data] if options.has_key?(:data)
165
+ ensure_supported_payload data
184
166
 
185
- send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Leave, client_id, options, &success_block)
167
+ send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Leave, client_id, data, &success_block)
186
168
  end
187
169
 
188
170
  # Update the presence data for this client. If the client is not already a member of
189
171
  # the presence set it will be added, and presence subscribers will see an enter or
190
172
  # update message for this client.
191
173
  #
192
- # @param [Hash,String] options an options Hash to specify client data
193
- # @option options [String] :data optional data (eg a status message) for this member
174
+ # @param (see Presence#enter)
194
175
  #
195
176
  # @yield (see Presence#enter)
196
177
  # @return (see Presence#enter)
197
178
  #
198
- def update(options = {}, &success_block)
199
- data = options.fetch(:data, nil)
179
+ def update(data = nil, &success_block)
200
180
  deferrable = create_deferrable
201
181
 
202
- ensure_supported_client_id client_id
203
- ensure_supported_payload data unless data.nil?
182
+ ensure_supported_payload data
204
183
 
205
184
  @data = data
206
185
 
@@ -224,17 +203,15 @@ module Ably::Realtime
224
203
  # enables it to represent an arbitrary clientId.
225
204
  #
226
205
  # @param (see Presence#enter_client)
227
- # @option options (see Presence#enter_client)
228
206
  #
229
207
  # @yield (see Presence#enter_client)
230
208
  # @return (see Presence#enter_client)
231
209
  #
232
- def update_client(client_id, options = {}, &success_block)
233
- raise ArgumentError, 'options must be a Hash' unless options.kind_of?(Hash)
210
+ def update_client(client_id, data = nil, &success_block)
234
211
  ensure_supported_client_id client_id
235
- ensure_supported_payload options[:data] if options.has_key?(:data)
212
+ ensure_supported_payload data
236
213
 
237
- send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Update, client_id, options, &success_block)
214
+ send_presence_action_for_client(Ably::Models::PresenceMessage::ACTION.Update, client_id, data, &success_block)
238
215
  end
239
216
 
240
217
  # Get the presence state for this Channel.
@@ -250,11 +227,11 @@ module Ably::Realtime
250
227
  ensure_channel_attached(deferrable) do
251
228
  members.get(options).tap do |members_map_deferrable|
252
229
  members_map_deferrable.callback do |*args|
253
- safe_yield block, *args if block_given?
254
- deferrable.succeed *args
230
+ safe_yield(block, *args) if block_given?
231
+ deferrable.succeed(*args)
255
232
  end
256
233
  members_map_deferrable.errback do |*args|
257
- deferrable.fail *args
234
+ deferrable.fail(*args)
258
235
  end
259
236
  end
260
237
  end
@@ -344,8 +321,8 @@ module Ably::Realtime
344
321
  end
345
322
 
346
323
  # @return [Ably::Models::PresenceMessage] presence message is returned allowing callbacks to be added
347
- def send_presence_protocol_message(presence_action, client_id, options = {})
348
- presence_message = create_presence_message(presence_action, client_id, options)
324
+ def send_presence_protocol_message(presence_action, client_id, data)
325
+ presence_message = create_presence_message(presence_action, client_id, data)
349
326
  unless presence_message.client_id
350
327
  raise Ably::Exceptions::Standard.new('Unable to enter create presence message without a client_id', 400, 91000)
351
328
  end
@@ -361,12 +338,12 @@ module Ably::Realtime
361
338
  presence_message
362
339
  end
363
340
 
364
- def create_presence_message(action, client_id, options = {})
341
+ def create_presence_message(action, client_id, data)
365
342
  model = {
366
343
  action: Ably::Models::PresenceMessage.ACTION(action).to_i,
367
- clientId: client_id
344
+ clientId: client_id,
345
+ data: data
368
346
  }
369
- model.merge!(data: options.fetch(:data)) if options.has_key?(:data)
370
347
 
371
348
  Ably::Models::PresenceMessage.new(model, logger: logger).tap do |presence_message|
372
349
  presence_message.encode self.channel
@@ -406,13 +383,7 @@ module Ably::Realtime
406
383
  target_state = options.fetch(:target_state, nil)
407
384
  failed_state = options.fetch(:failed_state, nil)
408
385
 
409
- protocol_message_options = if options.has_key?(:data)
410
- { data: options.fetch(:data) }
411
- else
412
- { }
413
- end
414
-
415
- send_presence_protocol_message(action, client_id, protocol_message_options).tap do |protocol_message|
386
+ send_presence_protocol_message(action, client_id, options[:data]).tap do |protocol_message|
416
387
  protocol_message.callback do |message|
417
388
  change_state target_state, message if target_state
418
389
  deferrable_succeed deferrable, &success_block
@@ -426,23 +397,23 @@ module Ably::Realtime
426
397
  end
427
398
 
428
399
  def deferrable_succeed(deferrable, *args, &block)
429
- safe_yield block, self, *args if block_given?
400
+ safe_yield(block, self, *args) if block_given?
430
401
  EventMachine.next_tick { deferrable.succeed self, *args } # allow callback to be added to the returned Deferrable before calling succeed
431
402
  deferrable
432
403
  end
433
404
 
434
405
  def deferrable_fail(deferrable, *args, &block)
435
- safe_yield block, *args if block_given?
436
- EventMachine.next_tick { deferrable.fail *args } # allow errback to be added to the returned Deferrable
406
+ safe_yield(block, *args) if block_given?
407
+ EventMachine.next_tick { deferrable.fail(*args) } # allow errback to be added to the returned Deferrable
437
408
  deferrable
438
409
  end
439
410
 
440
- def send_presence_action_for_client(action, client_id, options = {}, &success_block)
411
+ def send_presence_action_for_client(action, client_id, data, &success_block)
441
412
  ensure_presence_publishable_on_connection
442
413
 
443
414
  deferrable = create_deferrable
444
415
  ensure_channel_attached(deferrable) do
445
- send_presence_protocol_message(action, client_id, options).tap do |protocol_message|
416
+ send_presence_protocol_message(action, client_id, data).tap do |protocol_message|
446
417
  protocol_message.callback { |message| deferrable_succeed deferrable, &success_block }
447
418
  protocol_message.errback { |error| deferrable_fail deferrable, error }
448
419
  end