Class: Ably::Realtime::Client

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

Overview

Client for the Ably Realtime API

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:

# create a new client authenticating with basic auth
client = Ably::Realtime::Client.new('key.id:secret')

# create a new client and configure a client ID used for presence
client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')

Parameters:

  • options (Hash, String)

    an options Hash used to configure the client and the authentication, or String with an API key or Token ID

Options Hash (options):

  • :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.

  • :disconnected_retry_timeout (Integer) — default: 15 seconds

    . When the connection enters the DISCONNECTED state, after this delay in milliseconds, 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 milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically

  • :tls (Boolean) — default: true

    When fales, TLS is disabled. Please note Basic Auth is disallowed without TLS as secrets cannot be transmitted over unsecured connections.

  • :key (String)

    API key comprising the key name and key secret in a single string

  • :token (String)

    Token string or Models::TokenDetails used to authenticate requests

  • :token_details (String)

    Models::TokenDetails used to authenticate requests

  • :use_token_auth (Boolean)

    Will force Basic Auth if set to false, and Token auth if set to true

  • :environment (String)

    Specify ‘sandbox’ when testing the client library against an alternate Ably environment

  • :protocol (Symbol) — default: :msgpack

    Protocol used to communicate with Ably, :json and :msgpack currently supported

  • :use_binary_protocol (Boolean) — default: true

    When true will use the MessagePack binary protocol, when false it will use JSON encoding. This option will overide :protocol option

  • :log_level (Logger::Severity, Symbol) — default: Logger::WARN

    Log level for the standard Logger that outputs to STDOUT. Can be set to :fatal (Logger::FATAL), :error (Logger::ERROR), :warn (Logger::WARN), :info (Logger::INFO), :debug (Logger::DEBUG) or :none

  • :logger (Logger)

    A custom logger can be used however it must adhere to the Ruby Logger interface, see www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html

  • :client_id (String)

    client ID identifying this connection to other clients

  • :auth_url (String)

    a URL to be used to GET or POST a set of token request params, to obtain a signed token request

  • :auth_headers (Hash)

    a set of application-specific headers to be added to any request made to the auth_url

  • :auth_params (Hash)

    a set of application-specific query params to be added to any request made to the auth_url

  • :auth_method (Symbol) — default: :get

    HTTP method to use with auth_url, must be either :get or :post

  • :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. The Proc should return a token string, Models::TokenDetails or JSON equivalent, Models::TokenRequest or JSON equivalent

  • :query_time (Boolean)

    when true will query the Ably system for the current time instead of using the local time

  • :token_params (Hash)

    convenience to pass in token_params that will be used as a default for all token requests. See Auth#create_token_request

  • :http_open_timeout (Integer) — default: 4 seconds

    timeout in seconds for opening an HTTP connection for all HTTP requests

  • :http_request_timeout (Integer) — default: 15 seconds

    timeout in seconds for any single complete HTTP request and response

  • :http_max_retry_count (Integer) — default: 3

    maximum number of fallback host retries for HTTP requests that fail due to network issues or server problems

  • :http_max_retry_duration (Integer) — default: 10 seconds

    maximum elapsed time in which fallback host retries for HTTP requests will be attempted i.e. if the first default host attempt takes 5s, and then the subsequent fallback retry attempt takes 7s, no further fallback host attempts will be made as the total elapsed time of 12s exceeds the default 10s limit

Raises:

  • (ArgumentError)


88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ably/realtime/client.rb', line 88

def initialize(options)
  @rest_client           = Ably::Rest::Client.new(options)
  @auth                  = Ably::Realtime::Auth.new(self)
  @channels              = Ably::Realtime::Channels.new(self)
  @connection            = Ably::Realtime::Connection.new(self, options)
  @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
  @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
  @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
  @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
  @recover               = rest_client.options[:recover]

  raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
end

Instance Attribute Details

#authAbly::Auth (readonly)

Auth authentication object configured for this connection

Returns:



31
32
33
# File 'lib/ably/realtime/client.rb', line 31

def auth
  @auth
end

#auth_optionsHash (readonly)

Returns Auth options configured for this client.

Returns:

  • (Hash)

    Auth options configured for this client



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
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)


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

def auto_connect
  @auto_connect
end

#channelsAby::Realtime::Channels (readonly)

The collection of Ably::Realtime::Channels that have been created

Returns:

  • (Aby::Realtime::Channels)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
end

#client_idString (readonly)

Returns A client ID, used for identifying this client for presence purposes.

Returns:

  • (String)

    A client ID, used for identifying this client for presence purposes



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
end

#connectionAby::Realtime::Connection (readonly)

The underlying connection for this client

Returns:

  • (Aby::Realtime::Connection)


35
36
37
# File 'lib/ably/realtime/client.rb', line 35

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)


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

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)


43
44
45
# File 'lib/ably/realtime/client.rb', line 43

def echo_messages
  @echo_messages
end

#encodersArray<Ably::Models::MessageEncoder::Base> (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.

The registered encoders that are used to encode and decode message payloads

Returns:

  • (Array<Ably::Models::MessageEncoder::Base>)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
end

#endpointURI::Generic (readonly)

Returns Default Ably Realtime endpoint used for all requests.

Returns:

  • (URI::Generic)

    Default Ably Realtime endpoint used for all requests



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

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

#environmentString (readonly)

Custom environment to use such as ‘sandbox’ when testing the client library against an alternate Ably environment

Returns:

  • (String)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
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 is used.

Returns:

  • (URI::Generic)

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



173
174
175
176
177
178
179
180
181
# File 'lib/ably/realtime/client.rb', line 173

def fallback_endpoint
  unless defined?(@fallback_endpoints) && @fallback_endpoints
    @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
  end

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

  @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
end

#protocolSymbol (readonly)

The protocol configured for this client, either binary ‘:msgpack` or text based `:json`

Returns:

  • (Symbol)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
end

#protocol_binary?Boolean (readonly)

Returns True of the transport #protocol communicates with Ably with a binary protocol.

Returns:

  • (Boolean)

    True of the transport #protocol communicates with Ably with a binary protocol



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ably/realtime/client.rb', line 20

class Client
  include Ably::Modules::AsyncWrapper
  extend Forwardable

  DOMAIN = 'realtime.ably.io'

  # The collection of {Ably::Realtime::Channel}s that have been created
  # @return [Aby::Realtime::Channels]
  attr_reader :channels

  # (see Ably::Rest::Client#auth)
  attr_reader :auth

  # The underlying connection for this client
  # @return [Aby::Realtime::Connection]
  attr_reader :connection

  # The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
  # @return [Ably::Rest::Client]
  attr_reader :rest_client

  # When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
  # @return [Boolean]
  attr_reader :echo_messages

  # If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states. Defaults to true
  # @return [Boolean]
  attr_reader :queue_messages

  # The custom realtime websocket host that is being used if it was provided with the option `:ws_host` when the {Client} was created
  # @return [String,Nil]
  attr_reader :custom_realtime_host

  # 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
  # @return [Boolean]
  attr_reader :auto_connect

  # 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
  # @return [String,Nil]
  attr_reader :recover

  def_delegators :auth, :client_id, :auth_options
  def_delegators :@rest_client, :encoders
  def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
  def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
  def_delegators :@rest_client, :log_level

  # Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
  #
  # @param (see Ably::Rest::Client#initialize)
  # @option options (see Ably::Rest::Client#initialize)
  # @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
  # @option options [Boolean] :echo_messages  If false, prevents messages originating from this connection being echoed back on the same connection
  # @option options [String]  :recover        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
  # @option options [Boolean] :auto_connect   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.
  #
  # @option options [Integer] :disconnected_retry_timeout  (15 seconds). When the connection enters the DISCONNECTED state, after this delay in milliseconds, if the state is still DISCONNECTED, the client library will attempt to reconnect automatically
  # @option options [Integer] :suspended_retry_timeout     (30 seconds). When the connection enters the SUSPENDED state, after this delay in milliseconds, if the state is still SUSPENDED, the client library will attempt to reconnect automatically
  #
  # @return [Ably::Realtime::Client]
  #
  # @example
  #    # create a new client authenticating with basic auth
  #    client = Ably::Realtime::Client.new('key.id:secret')
  #
  #    # create a new client and configure a client ID used for presence
  #    client = Ably::Realtime::Client.new(key: 'key.id:secret', client_id: 'john')
  #
  def initialize(options)
    @rest_client           = Ably::Rest::Client.new(options)
    @auth                  = Ably::Realtime::Auth.new(self)
    @channels              = Ably::Realtime::Channels.new(self)
    @connection            = Ably::Realtime::Connection.new(self, options)
    @echo_messages         = rest_client.options.fetch(:echo_messages, true) == false ? false : true
    @queue_messages        = rest_client.options.fetch(:queue_messages, true) == false ? false : true
    @custom_realtime_host  = rest_client.options[:realtime_host] || rest_client.options[:ws_host]
    @auto_connect          = rest_client.options.fetch(:auto_connect, true) == false ? false : true
    @recover               = rest_client.options[:recover]

    raise ArgumentError, "Recovery key '#{recover}' is invalid" if recover && !recover.match(Connection::RECOVER_REGEX)
  end

  # Return a {Ably::Realtime::Channel Realtime Channel} for the given name
  #
  # @param (see Ably::Realtime::Channels#get)
  # @return (see Ably::Realtime::Channels#get)
  #
  def channel(name, channel_options = {})
    channels.get(name, channel_options)
  end

  # Retrieve the Ably service time
  #
  # @yield [Time] The time as reported by the Ably service
  # @return [Ably::Util::SafeDeferrable]
  #
  def time(&success_callback)
    async_wrap(success_callback) do
      rest_client.time
    end
  end

  # Retrieve the stats for the application
  #
  # @param (see Ably::Rest::Client#stats)
  # @option options (see Ably::Rest::Client#stats)
  #
  # @yield [Ably::Models::PaginatedResult<Ably::Models::Stats>] An Array of Stats
  #
  # @return [Ably::Util::SafeDeferrable]
  #
  def stats(options = {}, &success_callback)
    async_wrap(success_callback) do
      rest_client.stats(options)
    end
  end

  # (see Ably::Realtime::Connection#close)
  def close(&block)
    connection.close(&block)
  end

  # (see Ably::Realtime::Connection#connect)
  def connect(&block)
    connection.connect(&block)
  end

  # @!attribute [r] endpoint
  # @return [URI::Generic] Default Ably Realtime endpoint used for all requests
  def endpoint
    endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
  end

  # (see Ably::Rest::Client#register_encoder)
  def register_encoder(encoder)
    rest_client.register_encoder encoder
  end

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

  # Disable connection recovery, typically used after a connection has been recovered
  # @return [void]
  # @api private
  def disable_automatic_connection_recovery
    @recover = nil
  end

  # @!attribute [r] fallback_endpoint
  # @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
  # @api private
  def fallback_endpoint
    unless defined?(@fallback_endpoints) && @fallback_endpoints
      @fallback_endpoints = Ably::FALLBACK_HOSTS.shuffle.map { |fallback_host| endpoint_for_host(fallback_host) }
    end

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

    @fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
  end

  private
  def endpoint_for_host(host)
    port = if use_tls?
      custom_tls_port
    else
      custom_port
    end

    raise ArgumentError, "Custom port must be an Integer or nil" if port && !port.kind_of?(Integer)

    options = {
      scheme: use_tls? ? 'wss' : 'ws',
      host:   host
    }
    options.merge!(port: port) if port

    URI::Generic.build(options)
  end
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)


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

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)


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

def recover
  @recover
end

#rest_clientAbly::Rest::Client (readonly)

The REST client instantiated with the same credentials and configuration that is used for all REST operations such as authentication

Returns:



39
40
41
# File 'lib/ably/realtime/client.rb', line 39

def rest_client
  @rest_client
end

Instance Method Details

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

Return a Realtime Channel for the given name

Parameters:

  • name (String)

    The name of the channel

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

    Channel options, currently reserved for Encryption options

Returns:



107
108
109
# File 'lib/ably/realtime/client.rb', line 107

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

#close { ... } ⇒ EventMachine::Deferrable

Causes the connection to close, entering the closed state, from any state except the failed state. Once closed, the library will not attempt to re-establish the connection without a call to Ably::Realtime::Connection#connect.

Yields:

  • block is called as soon as this connection is in the Closed state

Returns:

  • (EventMachine::Deferrable)


138
139
140
# File 'lib/ably/realtime/client.rb', line 138

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

#connect { ... } ⇒ EventMachine::Deferrable

Causes the library to attempt connection. If it was previously explicitly closed by the user, or was closed as a result of an unrecoverable error, a new connection will be opened. Succeeds when connection is established i.e. state is @Connected@ Fails when state becomes either @Closing@, @Closed@ or @Failed@

Note that if the connection remains in the disconnected ans suspended states indefinitely, the Deferrable or block provided may never be called

Yields:

  • block is called as soon as this connection is in the Connected state

Returns:

  • (EventMachine::Deferrable)


143
144
145
# File 'lib/ably/realtime/client.rb', line 143

def connect(&block)
  connection.connect(&block)
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



166
167
168
# File 'lib/ably/realtime/client.rb', line 166

def disable_automatic_connection_recovery
  @recover = nil
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



159
160
161
# File 'lib/ably/realtime/client.rb', line 159

def logger
  @logger ||= Ably::Logger.new(self, log_level, rest_client.logger.custom_logger)
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:



154
155
156
# File 'lib/ably/realtime/client.rb', line 154

def register_encoder(encoder)
  rest_client.register_encoder encoder
end

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

Retrieve the stats for the application

Parameters:

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

    the options for the stats request

Options Hash (options):

  • :start (Integer, Time)

    Ensure earliest time or millisecond since epoch for any stats retrieved is :start

  • :end (Integer, Time)

    Ensure latest time or millisecond since epoch for any stats retrieved is :end

  • :direction (Symbol)

    :forwards or :backwards, defaults to :backwards

  • :limit (Integer)

    Maximum number of messages to retrieve up to 1,000, defaults to 100

  • :unit (Symbol)

    ‘:minute`, `:hour`, `:day` or `:month`. Defaults to `:minute`

Yields:

Returns:



131
132
133
134
135
# File 'lib/ably/realtime/client.rb', line 131

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

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

Retrieve the Ably service time

Yields:

  • (Time)

    The time as reported by the Ably service

Returns:



116
117
118
119
120
# File 'lib/ably/realtime/client.rb', line 116

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