Class: Ably::Realtime::Client

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Modules::AsyncWrapper, Modules::Conversions, Ably::Realtime::Channel::Publisher
Defined in:
lib/ably/realtime/client.rb,
lib/ably/realtime/client/incoming_message_dispatcher.rb,
lib/ably/realtime/client/outgoing_message_dispatcher.rb

Overview

A client that extends the functionality of the Client and provides additional realtime-specific features.

Defined Under Namespace

Classes: IncomingMessageDispatcher, OutgoingMessageDispatcher

Constant Summary collapse

DOMAIN =
'realtime.ably.io'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Ably::Realtime::Client

Creates a Realtime Client and configures the Auth object for the connection.

Examples:

# Constructs a {Ably::Realtime::Client} object using an Ably API key or token string.
client = Ably::Realtime::Client.new('key.id:secret')

# Constructs a {Ably::Realtime::Client} object using an Ably options object.
client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')

Parameters:

  • options (Hash)

    a customizable set of options

Options Hash (options):

  • (see (Object)

    Ably::Rest::Client#initialize) An options Hash object.

  • :auth_callback (Proc)

    when provided, the Proc will be called with the token params hash as the first argument, whenever a new token is required. Whilst the proc is called synchronously, it does not block the EventMachine reactor as it is run in a separate thread. The Proc should return a token string, Models::TokenDetails or JSON equivalent, Models::TokenRequest or JSON equivalent

  • :queue_messages (Boolean)

    If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states

  • :echo_messages (Boolean)

    If false, prevents messages originating from this connection being echoed back on the same connection

  • :recover (String)

    When a recover option is specified a connection inherits the state of a previous connection that may have existed under a different instance of the Realtime library, please refer to the API documentation for further information on connection state recovery

  • :auto_connect (Boolean)

    By default as soon as the client library is instantiated it will connect to Ably. You can optionally set this to false and explicitly connect.

  • :transport_params (Hash)

    Additional parameters to be sent in the querystring when initiating a realtime connection. Keys are Strings, values are Stringifiable(a value must respond to #to_s)

  • :channel_retry_timeout (Integer) — default: 15 seconds

    . When a channel becomes SUSPENDED, after this delay in seconds, the channel will automatically attempt to reattach if the connection is CONNECTED

  • :disconnected_retry_timeout (Integer) — default: 15 seconds

    . When the connection enters the DISCONNECTED state, after this delay in seconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically

  • :suspended_retry_timeout (Integer) — default: 30 seconds

    . When the connection enters the SUSPENDED state, after this delay in seconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically

  • :disable_websocket_heartbeats (Boolean)

    WebSocket heartbeats are more efficient than protocol level heartbeats, however they can be disabled for development purposes

Raises:

  • (ArgumentError)


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/ably/realtime/client.rb', line 109

def initialize(options)
  raise ArgumentError, 'Options Hash is expected' if options.nil?

  options = options.clone
  if options.kind_of?(String)
    options = if options.match(Ably::Auth::API_KEY_REGEX)
      { key: options }
    else
      { token: options }
    end
  end

  @transport_params      = options.delete(:transport_params).to_h.each_with_object({}) do |(key, value), acc|
    acc[key.to_s] = value.to_s
  end
  @rest_client           = Ably::Rest::Client.new(options.merge(realtime_client: self))
  @echo_messages         = rest_client.options.fetch_with_default(:echo_messages, true)
  @queue_messages        = rest_client.options.fetch_with_default(:queue_messages, true)
  @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
  @auto_connect          = rest_client.options.fetch_with_default(:auto_connect, true)
  @recover               = rest_client.options.fetch_with_default(:recover, '')

  @auth       = Ably::Realtime::Auth.new(self)
  @channels   = Ably::Realtime::Channels.new(self)
  @connection = Ably::Realtime::Connection.new(self, options)

  unless @recover.nil_or_empty?
    recovery_context = RecoveryKeyContext.from_json(@recover, logger)
    unless recovery_context.nil?
      @channels.set_channel_serials recovery_context.channel_serials # RTN16j
      @connection.set_msg_serial_from_recover = recovery_context.msg_serial  # RTN16f
    end
  end
end

Instance Attribute Details

#authAbly::Auth (readonly)

An Auth object.

Returns:



33
34
35
# File 'lib/ably/realtime/client.rb', line 33

def auth
  @auth
end

#auto_connectBoolean (readonly)

When true, as soon as the client library is instantiated it will connect to Ably. If this attribute is false, a connection must be opened explicitly

Returns:

  • (Boolean)


63
64
65
# File 'lib/ably/realtime/client.rb', line 63

def auto_connect
  @auto_connect
end

#channelsAby::Realtime::Channels (readonly)

A Aby::Realtime::Channels object.

Returns:

  • (Aby::Realtime::Channels)


25
26
27
# File 'lib/ably/realtime/client.rb', line 25

def channels
  @channels
end

#connectionAby::Realtime::Connection (readonly)

A Aby::Realtime::Connection object.

Returns:

  • (Aby::Realtime::Connection)


41
42
43
# File 'lib/ably/realtime/client.rb', line 41

def connection
  @connection
end

#custom_realtime_hostString, Nil (readonly)

The custom realtime websocket host that is being used if it was provided with the option ‘:ws_host` when the Ably::Realtime::Client was created

Returns:

  • (String, Nil)


59
60
61
# File 'lib/ably/realtime/client.rb', line 59

def custom_realtime_host
  @custom_realtime_host
end

#echo_messagesBoolean (readonly)

When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true

Returns:

  • (Boolean)


51
52
53
# File 'lib/ably/realtime/client.rb', line 51

def echo_messages
  @echo_messages
end

#endpointURI::Generic (readonly)

Returns Default Ably Realtime endpoint used for all requests.

Returns:

  • (URI::Generic)

    Default Ably Realtime endpoint used for all requests



294
295
296
# File 'lib/ably/realtime/client.rb', line 294

def endpoint
  endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
end

#fallback_endpointURI::Generic (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Fallback endpoint used to connect to the realtime Ably service. Note, after each connection attempt, a new random fallback host or provided fallback hosts are used.

Returns:

  • (URI::Generic)

    Fallback endpoint used to connect to the realtime Ably service. Note, after each connection attempt, a new random fallback host or provided fallback hosts are used



323
324
325
326
327
328
329
330
331
332
# File 'lib/ably/realtime/client.rb', line 323

def fallback_endpoint
  unless defined?(@fallback_endpoints) && @fallback_endpoints
    @fallback_endpoints = fallback_hosts.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    @fallback_endpoints << endpoint # Try the original host last if all fallbacks have been used
  end

  fallback_endpoint_index = connection.manager.retry_count_for_state(:disconnected) + connection.manager.retry_count_for_state(:suspended) - 1

  @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
end

#queue_messagesBoolean (readonly)

If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true

Returns:

  • (Boolean)


55
56
57
# File 'lib/ably/realtime/client.rb', line 55

def queue_messages
  @queue_messages
end

#recoverString, Nil (readonly)

When a recover option is specified a connection inherits the state of a previous connection that may have existed under a different instance of the Realtime library, please refer to the API documentation for further information on connection state recovery

Returns:

  • (String, Nil)


67
68
69
# File 'lib/ably/realtime/client.rb', line 67

def recover
  @recover
end

#rest_clientObject (readonly)



47
48
49
# File 'lib/ably/realtime/client.rb', line 47

def rest_client
  @rest_client
end

#transport_paramsHash (readonly)

Additional parameters to be sent in the querystring when initiating a realtime connection

Returns:

  • (Hash)


71
72
73
# File 'lib/ably/realtime/client.rb', line 71

def transport_params
  @transport_params
end

Instance Method Details

#channel(name, channel_options = {}) ⇒ Ably::Realtime::Channel

Return a Realtime Channel for the given name

Parameters:

Returns:



149
150
151
# File 'lib/ably/realtime/client.rb', line 149

def channel(name, channel_options = {})
  channels.get(name, channel_options)
end

#close(&block) ⇒ Object

Calls Ably::Realtime::Connection#close and causes the connection to close, entering the closing state. Once closed, the library will not attempt to re-establish the connection without an explicit call to Ably::Realtime::Connection#connect. (see Ably::Realtime::Connection#close)



190
191
192
# File 'lib/ably/realtime/client.rb', line 190

def close(&block)
  connection.close(&block)
end

#connect(&block) ⇒ Object

Calls Ably::Realtime::Connection#connect and causes the connection to open, entering the connecting state. Explicitly calling connect() is unnecessary unless the autoConnect property is disabled. (see Ably::Realtime::Connection#connect)



198
199
200
# File 'lib/ably/realtime/client.rb', line 198

def connect(&block)
  connection.connect(&block)
end

#deviceAbly::Models::LocalDevice

Note:

This is unsupported in the Ruby library

Retrieves a Models::LocalDevice object that represents the current state of the device as a target for push notifications.

Returns:

  • (Ably::Models::LocalDevice)

    A Models::LocalDevice object.

Raises:



339
340
341
# File 'lib/ably/realtime/client.rb', line 339

def device
  raise Ably::Exceptions::PushNotificationsNotSupported, 'This device does not support receiving or subscribing to push notifications. The local device object is not unavailable'
end

#disable_automatic_connection_recoveryvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Disable connection recovery, typically used after a connection has been recovered



316
317
318
# File 'lib/ably/realtime/client.rb', line 316

def disable_automatic_connection_recovery
  @recover = nil
end

#fallback_hostsObject

The list of fallback hosts to be used by this client if empty or nil then fallback host functionality is disabled



304
305
306
# File 'lib/ably/realtime/client.rb', line 304

def fallback_hosts
  rest_client.fallback_hosts
end

#loggerLogger

Returns The Logger for this client. Configure the log_level with the ‘:log_level` option, refer to #initialize.

Returns:

  • (Logger)

    The Logger for this client. Configure the log_level with the ‘:log_level` option, refer to #initialize



309
310
311
# File 'lib/ably/realtime/client.rb', line 309

def logger
  @logger ||= Ably::Logger.new(self, log_level, rest_client.logger.custom_logger)
end

#publish(channel_name, name, data = nil, attributes = {}) {|Ably::Models::Message, Array<Ably::Models::Message>| ... } ⇒ Ably::Util::SafeDeferrable

Publish one or more messages to the specified channel.

This method allows messages to be efficiently published to Ably without instancing a Ably::Realtime::Channel object. If you want to publish a high rate of messages to Ably without instancing channels or using the REST API, then this method is recommended. However, channel options such as encryption are not supported with this method. If you need to specify channel options we recommend you use the Ably::Realtime::Channel publish method without attaching to each channel, unless you also want to subscribe to published messages on that channel.

Note: This feature is still in beta. As such, we cannot guarantee the API will not change in future.

Examples:

# Publish a single message
client.publish 'activityChannel', click', { x: 1, y: 2 }

# Publish an array of message Hashes
messages = [
  { name: 'click', { x: 1, y: 2 } },
  { name: 'click', { x: 2, y: 3 } }
]
client.publish 'activityChannel', messages

# Publish an array of Ably::Models::Message objects
messages = [
  Ably::Models::Message(name: 'click', { x: 1, y: 2 })
  Ably::Models::Message(name: 'click', { x: 2, y: 3 })
]
client.publish 'activityChannel', messages

client.publish('activityChannel', 'click', 'body') do |message|
  puts "#{message.name} event received with #{message.data}"
end

client.publish('activityChannel', 'click', 'body').errback do |error, message|
  puts "#{message.name} was not received, error #{error.message}"
end

Parameters:

  • channel (String)

    The channel name you want to publish the message(s) to

  • name (String, Array<Ably::Models::Message|Hash>, nil)

    The event name of the message to publish, or an Array of [Ably::Model::Message] objects or [Hash] objects with :name and :data pairs

  • data (String, ByteArray, nil) (defaults to: nil)

    The message payload unless an Array of [Ably::Model::Message] objects passed in the first argument

  • attributes (Hash, nil) (defaults to: {})

    Optional additional message attributes such as :client_id or :connection_id, applied when name attribute is nil or a string

Yields:

Returns:



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/ably/realtime/client.rb', line 268

def publish(channel_name, name, data = nil, attributes = {}, &success_block)
  if !connection.can_publish_messages?
    error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is not allowed to queue messages when connection is in state #{connection.state}")
    return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
  end

  messages = if name.kind_of?(Enumerable)
    name
  else
    name = ensure_utf_8(:name, name, allow_nil: true)
    ensure_supported_payload data
    [{ name: name, data: data }.merge(attributes)]
  end

  if messages.length > Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE
    error = Ably::Exceptions::InvalidRequest.new("It is not possible to publish more than #{Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE} messages with a single publish request.")
    return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
  end

  enqueue_messages_on_connection(self, messages, channel_name).tap do |deferrable|
    deferrable.callback(&success_block) if block_given?
  end
end

#pushAbly::Realtime::Push

A Push object.



204
205
206
# File 'lib/ably/realtime/client.rb', line 204

def push
  @push ||= Push.new(self)
end

#register_encoder(encoder) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Encoders and decoders are processed in the order they are added so the first encoder will be given priority when encoding and decoding

This method returns an undefined value.

Register a message encoder and decoder that implements Ably::Models::MessageEncoders::Base interface. Message encoders are used to encode and decode message payloads automatically.

Parameters:



299
300
301
# File 'lib/ably/realtime/client.rb', line 299

def register_encoder(encoder)
  rest_client.register_encoder encoder
end

#request(method, path, params = {}, body = nil, headers = {}) {|Ably::Models::HttpPaginatedResponse<>| ... } ⇒ Ably::Util::SafeDeferrable

Makes a REST request to a provided path. This is provided as a convenience for developers who wish to use REST API functionality that is either not documented or is not yet included in the public API, without having to directly handle features such as authentication, paging, fallback hosts, MsgPack and JSON support.

(see Ably::Rest::Client#request)

Yields:

Returns:



218
219
220
221
222
# File 'lib/ably/realtime/client.rb', line 218

def request(method, path, params = {}, body = nil, headers = {}, &callback)
  async_wrap(callback) do
    rest_client.request(method, path, params, body, headers, async_blocking_operations: true)
  end
end

#stats(options = {}) {|Ably::Models::PaginatedResult<Ably::Models::Stats>| ... } ⇒ Ably::Util::SafeDeferrable

Queries the REST /stats API and retrieves your application’s usage statistics. Returns a Util::SafeDeferrable object, containing an array of Models::Stats objects. See the Stats docs.

Parameters:

  • options (Hash) (defaults to: {})

    the options for the stats request

Options Hash (options):

  • :start (Integer, Time)

    The time from which stats are retrieved, specified as milliseconds since the Unix epoch. RSC6b1

  • :end (Integer, Time)

    The time until stats are retrieved, specified as milliseconds since the Unix epoch. RSC6b1

  • :direction (Symbol)

    The order for which stats are returned in. Valid values are backwards which orders stats from most recent to oldest, or forwards which orders stats from oldest to most recent. The default is backwards. RSC6b2

  • :limit (Integer)

    An upper limit on the number of stats returned. The default is 100, and the maximum is 1000. RSC6b3

  • :unit (Symbol)

    minute, hour, day or month. Based on the unit selected, the given start or end times are rounded down to the start of the relevant interval depending on the unit granularity of the query. RSC6b4

Yields:

Returns:



180
181
182
183
184
# File 'lib/ably/realtime/client.rb', line 180

def stats(options = {}, &success_callback)
  async_wrap(success_callback) do
    rest_client.stats(options)
  end
end

#time {|Time| ... } ⇒ Ably::Util::SafeDeferrable

Retrieves the time from the Ably service as milliseconds since the Unix epoch. Clients that do not have access to a sufficiently well maintained time source and wish to issue Ably Models::TokenRequests with a more accurate timestamp should use the queryTime property instead of this method.

Yields:

  • (Time)

    The time as milliseconds since the Unix epoch.

Returns:



162
163
164
165
166
# File 'lib/ably/realtime/client.rb', line 162

def time(&success_callback)
  async_wrap(success_callback) do
    rest_client.time
  end
end