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