ably-rest 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/.travis.yml +1 -0
- data/SPEC.md +480 -472
- data/lib/ably-rest.rb +1 -1
- data/lib/submodules/ably-ruby/LICENSE.txt +1 -1
- data/lib/submodules/ably-ruby/README.md +107 -24
- data/lib/submodules/ably-ruby/SPEC.md +531 -398
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +24 -16
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +9 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +17 -9
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_resource.rb +12 -8
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +18 -10
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +15 -4
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +4 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +31 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +77 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +71 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +28 -8
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +0 -5
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -29
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +54 -11
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +21 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +7 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +29 -26
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +41 -9
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +72 -24
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +26 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +19 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +74 -208
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +264 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_manager.rb +59 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_state_machine.rb +64 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +6 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/util/pub_sub.rb +3 -1
- data/lib/submodules/ably-ruby/lib/ably/util/safe_deferrable.rb +18 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +28 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +116 -46
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +55 -10
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +32 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +456 -96
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +96 -7
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +8 -0
- data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +71 -0
- data/lib/submodules/ably-ruby/spec/support/api_helper.rb +1 -1
- data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +1 -1
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +13 -7
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +15 -14
- data/lib/submodules/ably-ruby/spec/unit/models/paginated_resource_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +17 -17
- data/lib/submodules/ably-ruby/spec/unit/models/stat_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +28 -9
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +50 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +76 -2
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +51 -20
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +3 -3
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +52 -26
- data/lib/submodules/ably-ruby/spec/unit/realtime/safe_deferrable_spec.rb +12 -0
- data/spec/spec_helper.rb +5 -0
- metadata +12 -4
- data/lib/submodules/ably-ruby/.ruby-version.old +0 -1
@@ -0,0 +1,264 @@
|
|
1
|
+
module Ably::Realtime
|
2
|
+
class Presence
|
3
|
+
# A class encapsulating a map of the members of this presence channel,
|
4
|
+
# indexed by the unique {Ably::Models::PresenceMessage#member_key}
|
5
|
+
#
|
6
|
+
# This map synchronises the membership of the presence set by handling
|
7
|
+
# SYNC messages from the service. Since sync messages can be out-of-order -
|
8
|
+
# e.g. a PRESENT sync event being received after that member has in fact left -
|
9
|
+
# this map keeps "witness" entries, with ABSENT Action, to remember the
|
10
|
+
# fact that a LEAVE event has been seen for a member. These entries are
|
11
|
+
# cleared once the last set of updates of a sync sequence have been received.
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
class MembersMap
|
16
|
+
include Ably::Modules::EventEmitter
|
17
|
+
include Ably::Modules::SafeYield
|
18
|
+
include Enumerable
|
19
|
+
extend Ably::Modules::Enum
|
20
|
+
|
21
|
+
STATE = ruby_enum('STATE',
|
22
|
+
:initialized,
|
23
|
+
:sync_starting,
|
24
|
+
:in_sync,
|
25
|
+
:failed
|
26
|
+
)
|
27
|
+
include Ably::Modules::StateEmitter
|
28
|
+
|
29
|
+
# Number of absent members to cache internally whilst channel is in sync.
|
30
|
+
# Cache is unlimited until initial sync is complete ensuring users who have left are never reported as present.
|
31
|
+
MAX_ABSENT_MEMBER_CACHE = 100
|
32
|
+
|
33
|
+
def initialize(presence)
|
34
|
+
@presence = presence
|
35
|
+
|
36
|
+
@state = STATE(:initialized)
|
37
|
+
@members = Hash.new
|
38
|
+
@absent_member_cleanup_queue = []
|
39
|
+
|
40
|
+
setup_event_handlers
|
41
|
+
end
|
42
|
+
|
43
|
+
# When attaching to a channel that has members present, the server
|
44
|
+
# initiates a sync automatically so that the client has a complete list of members.
|
45
|
+
#
|
46
|
+
# Until this sync is complete, this method returns false
|
47
|
+
#
|
48
|
+
# @return [Boolean]
|
49
|
+
def sync_complete?
|
50
|
+
in_sync?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update the SYNC serial from the ProtocolMessage so that SYNC can be resumed.
|
54
|
+
# If the serial is nil, or the part after the first : is empty, then the SYNC is complete
|
55
|
+
#
|
56
|
+
# @return [void]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
def update_sync_serial(serial)
|
60
|
+
@sync_serial = serial
|
61
|
+
change_state :in_sync if sync_serial_cursor_at_end?
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get the list of presence members
|
65
|
+
#
|
66
|
+
# @param [Hash,String] options an options Hash to filter members
|
67
|
+
# @option options [String] :client_id optional client_id for the member
|
68
|
+
# @option options [String] :connection_id optional connection_id for the member
|
69
|
+
# @option options [String] :wait_for_sync defaults to true, if false the get method returns the current list of members and does not wait for the presence sync to complete
|
70
|
+
#
|
71
|
+
# @yield [Array<Ably::Models::PresenceMessage>] array of present members
|
72
|
+
#
|
73
|
+
# @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
|
74
|
+
#
|
75
|
+
def get(options = {}, &block)
|
76
|
+
wait_for_sync = options.fetch(:wait_for_sync, true)
|
77
|
+
deferrable = Ably::Util::SafeDeferrable.new(logger)
|
78
|
+
|
79
|
+
result_block = proc do
|
80
|
+
present_members.tap do |members|
|
81
|
+
members.keep_if { |member| member.connection_id == options[:connection_id] } if options[:connection_id]
|
82
|
+
members.keep_if { |member| member.client_id == options[:client_id] } if options[:client_id]
|
83
|
+
end.tap do |members|
|
84
|
+
safe_yield block, members if block_given?
|
85
|
+
deferrable.succeed members
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if !wait_for_sync || sync_complete?
|
90
|
+
result_block.call
|
91
|
+
else
|
92
|
+
# Must be defined before subsequent procs reference this callback
|
93
|
+
reset_callbacks = nil
|
94
|
+
|
95
|
+
in_sync_callback = proc do
|
96
|
+
reset_callbacks
|
97
|
+
result_block.call
|
98
|
+
end
|
99
|
+
|
100
|
+
failed_callback = proc do |error|
|
101
|
+
reset_callbacks
|
102
|
+
deferrable.fail error
|
103
|
+
end
|
104
|
+
|
105
|
+
reset_callbacks = proc do
|
106
|
+
off &in_sync_callback
|
107
|
+
off &failed_callback
|
108
|
+
channel.off &failed_callback
|
109
|
+
end
|
110
|
+
|
111
|
+
once :in_sync, &in_sync_callback
|
112
|
+
|
113
|
+
once(:failed, &failed_callback)
|
114
|
+
channel.unsafe_once(:detaching, :detached, :failed) do |error_reason|
|
115
|
+
failed_callback.call error_reason
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
deferrable
|
120
|
+
end
|
121
|
+
|
122
|
+
# @!attribute [r] length
|
123
|
+
# @return [Integer] number of present members known at this point in time, will not wait for sync operation to complete
|
124
|
+
def length
|
125
|
+
present_members.length
|
126
|
+
end
|
127
|
+
alias_method :count, :length
|
128
|
+
alias_method :size, :length
|
129
|
+
|
130
|
+
# Method to allow {MembersMap} to be {http://ruby-doc.org/core-2.1.3/Enumerable.html Enumerable}
|
131
|
+
# @note this method will not wait for the sync operation to complete so may return an incomplete set of members. Use {MembersMap#get} instead.
|
132
|
+
def each(&block)
|
133
|
+
return to_enum(:each) unless block_given?
|
134
|
+
present_members.each(&block)
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
attr_reader :members, :sync_serial, :presence, :absent_member_cleanup_queue
|
139
|
+
|
140
|
+
def channel
|
141
|
+
presence.channel
|
142
|
+
end
|
143
|
+
|
144
|
+
def client
|
145
|
+
channel.client
|
146
|
+
end
|
147
|
+
|
148
|
+
def logger
|
149
|
+
client.logger
|
150
|
+
end
|
151
|
+
|
152
|
+
def connection
|
153
|
+
client.connection
|
154
|
+
end
|
155
|
+
|
156
|
+
def setup_event_handlers
|
157
|
+
presence.__incoming_msgbus__.subscribe(:presence, :sync) do |presence_message|
|
158
|
+
presence_message.decode channel
|
159
|
+
update_members_and_emit_events presence_message
|
160
|
+
end
|
161
|
+
|
162
|
+
resume_sync_proc = method(:resume_sync).to_proc
|
163
|
+
connection.on_resume &resume_sync_proc
|
164
|
+
once(:in_sync, :failed) do
|
165
|
+
connection.off_resume &resume_sync_proc
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Trigger a manual SYNC operation to resume member synchronisation from last known cursor position
|
170
|
+
def resume_sync
|
171
|
+
connection.send_protocol_message(
|
172
|
+
action: Ably::Models::ProtocolMessage::ACTION.Sync.to_i,
|
173
|
+
channel: channel.name,
|
174
|
+
channel_serial: sync_serial
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
# When channel serial in ProtocolMessage SYNC is nil or
|
179
|
+
# an empty cursor appears after the ':' such as 'cf30e75054887:psl_7g:client:189'.
|
180
|
+
# That is an indication that there are no more SYNC messages.
|
181
|
+
def sync_serial_cursor_at_end?
|
182
|
+
sync_serial.nil? || sync_serial.to_s.match(/^[\w-]+:?$/)
|
183
|
+
end
|
184
|
+
|
185
|
+
def update_members_and_emit_events(presence_message)
|
186
|
+
return unless ensure_presence_message_is_valid(presence_message)
|
187
|
+
|
188
|
+
unless should_update_member?(presence_message)
|
189
|
+
logger.debug "#{self.class.name}: Skipped presence member #{presence_message.action} on channel #{presence.channel.name}.\n#{presence_message.to_json}"
|
190
|
+
return
|
191
|
+
end
|
192
|
+
|
193
|
+
case presence_message.action
|
194
|
+
when Ably::Models::PresenceMessage::ACTION.Enter, Ably::Models::PresenceMessage::ACTION.Update, Ably::Models::PresenceMessage::ACTION.Present
|
195
|
+
add_presence_member presence_message
|
196
|
+
when Ably::Models::PresenceMessage::ACTION.Leave
|
197
|
+
remove_presence_member presence_message
|
198
|
+
else
|
199
|
+
Ably::Exceptions::ProtocolError.new("Protocol error, unknown presence action #{presence_message.action}", 400, 80013)
|
200
|
+
end
|
201
|
+
|
202
|
+
clean_up_absent_members
|
203
|
+
end
|
204
|
+
|
205
|
+
def ensure_presence_message_is_valid(presence_message)
|
206
|
+
return true if presence_message.connection_id
|
207
|
+
|
208
|
+
error = Ably::Exceptions::ProtocolError.new("Protocol error, presence message is missing connectionId", 400, 80013)
|
209
|
+
logger.error "PresenceMap: On channel '#{channel.name}' error: #{error}"
|
210
|
+
channel.trigger :error, error
|
211
|
+
end
|
212
|
+
|
213
|
+
# If the message received is older than the last known event for presence
|
214
|
+
# then skip. This can occur during a SYNC operation. For example:
|
215
|
+
# - SYNC starts
|
216
|
+
# - LEAVE event received for clientId 5
|
217
|
+
# - SYNC present even received for clientId 5 with a timestamp before LEAVE event because the LEAVE occured before the SYNC operation completed
|
218
|
+
#
|
219
|
+
# @return [Boolean]
|
220
|
+
#
|
221
|
+
def should_update_member?(presence_message)
|
222
|
+
if members[presence_message.member_key]
|
223
|
+
members[presence_message.member_key].fetch(:message).timestamp < presence_message.timestamp
|
224
|
+
else
|
225
|
+
true
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def add_presence_member(presence_message)
|
230
|
+
logger.debug "#{self.class.name}: Member '#{presence_message.member_key}' for event '#{presence_message.action}' #{members.has_key?(presence_message.member_key) ? 'updated' : 'added'}.\n#{presence_message.to_json}"
|
231
|
+
members[presence_message.member_key] = { present: true, message: presence_message }
|
232
|
+
presence.emit_message presence_message.action, presence_message
|
233
|
+
end
|
234
|
+
|
235
|
+
def remove_presence_member(presence_message)
|
236
|
+
logger.debug "#{self.class.name}: Member '#{presence_message.member_key}' removed.\n#{presence_message.to_json}"
|
237
|
+
members[presence_message.member_key] = { present: false, message: presence_message }
|
238
|
+
absent_member_cleanup_queue << presence_message.member_key
|
239
|
+
presence.emit_message presence_message.action, presence_message
|
240
|
+
end
|
241
|
+
|
242
|
+
def present_members
|
243
|
+
members.select do |key, presence|
|
244
|
+
presence.fetch(:present)
|
245
|
+
end.map do |key, presence|
|
246
|
+
presence.fetch(:message)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def absent_members
|
251
|
+
members.reject do |key, presence|
|
252
|
+
presence.fetch(:present)
|
253
|
+
end.map do |key, presence|
|
254
|
+
presence.fetch(:message)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def clean_up_absent_members
|
259
|
+
return unless sync_complete?
|
260
|
+
members.delete absent_member_cleanup_queue.shift until absent_member_cleanup_queue.count <= MAX_ABSENT_MEMBER_CACHE
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Ably::Realtime
|
2
|
+
class Presence
|
3
|
+
# PresenceManager is responsible for all actions relating to presence state
|
4
|
+
#
|
5
|
+
# This is a private class and should never be used directly by developers as the API is likely to change in future.
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
class PresenceManager
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
# {Ably::Realtime::Presence} this Manager is associated with
|
13
|
+
# @return [Ably::Realtime::Presence]
|
14
|
+
attr_reader :presence
|
15
|
+
|
16
|
+
def initialize(presence)
|
17
|
+
@presence = presence
|
18
|
+
|
19
|
+
setup_channel_event_handlers
|
20
|
+
end
|
21
|
+
|
22
|
+
# Expect SYNC ProtocolMessages from the server with a list of current members on this channel
|
23
|
+
#
|
24
|
+
# @return [void]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def sync_expected
|
28
|
+
presence.members.change_state :sync_starting
|
29
|
+
end
|
30
|
+
|
31
|
+
# There server has indicated that there are no SYNC ProtocolMessages to come because
|
32
|
+
# there are no members on this channel
|
33
|
+
#
|
34
|
+
# @return [void]
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
def sync_not_expected
|
38
|
+
presence.members.change_state :in_sync
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def_delegators :presence, :members, :channel
|
43
|
+
|
44
|
+
def setup_channel_event_handlers
|
45
|
+
channel.unsafe_on(:detached) do
|
46
|
+
presence.transition_state_machine :left if presence.can_transition_to?(:left)
|
47
|
+
end
|
48
|
+
|
49
|
+
channel.unsafe_on(:failed) do |metadata|
|
50
|
+
presence.transition_state_machine :failed, metadata if presence.can_transition_to?(:failed)
|
51
|
+
end
|
52
|
+
|
53
|
+
presence.unsafe_on(:entered) do |message|
|
54
|
+
presence.set_connection_id message.connection_id
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'ably/modules/state_machine'
|
2
|
+
|
3
|
+
module Ably::Realtime
|
4
|
+
class Presence
|
5
|
+
# Internal class to manage presence state for {Ably::Realtime::Presence}
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
class PresenceStateMachine
|
10
|
+
include Ably::Modules::StateMachine
|
11
|
+
|
12
|
+
# States supported by this StateMachine match #{Presence::STATE}s
|
13
|
+
# :initialized
|
14
|
+
# :entering
|
15
|
+
# :entered
|
16
|
+
# :leaving
|
17
|
+
# :left
|
18
|
+
# :failed
|
19
|
+
Presence::STATE.each_with_index do |state_enum, index|
|
20
|
+
state state_enum.to_sym, initial: index == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# Entering or entered states can skip leaving and go straight to left if a channel is detached
|
24
|
+
# A channel that detaches very quickly will also go straight to :left from :initialized
|
25
|
+
# Failed states only occur when present and the channel fails or presence fails
|
26
|
+
transition :from => :initialized, :to => [:entering, :left]
|
27
|
+
transition :from => :entering, :to => [:entered, :leaving, :left, :failed]
|
28
|
+
transition :from => :entered, :to => [:leaving, :left, :failed]
|
29
|
+
transition :from => :leaving, :to => [:left, :entering, :failed]
|
30
|
+
transition :from => :failed, :to => [:entering]
|
31
|
+
|
32
|
+
after_transition do |presence, transition|
|
33
|
+
presence.synchronize_state_with_statemachine
|
34
|
+
end
|
35
|
+
|
36
|
+
after_transition(to: [:entering]) do |presence, current_transition|
|
37
|
+
presence.manager.enter current_transition.metadata
|
38
|
+
end
|
39
|
+
|
40
|
+
after_transition(to: [:leaving]) do |presence, current_transition|
|
41
|
+
presence.manager.leave current_transition.metadata
|
42
|
+
end
|
43
|
+
|
44
|
+
after_transition(to: [:failed]) do |presence, current_transition|
|
45
|
+
presence.manager.emit_error current_transition.metadata
|
46
|
+
end
|
47
|
+
|
48
|
+
# Transitions responsible for updating channel#error_reason
|
49
|
+
before_transition(to: [:left, :failed]) do |presence, current_transition|
|
50
|
+
presence.channel.set_failed_channel_error_reason current_transition.metadata if is_error_type?(current_transition.metadata)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def channel
|
55
|
+
object.channel
|
56
|
+
end
|
57
|
+
|
58
|
+
# Logged needs to be defined as it is used by {Ably::Modules::StateMachine}
|
59
|
+
def logger
|
60
|
+
channel.logger
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -67,7 +67,7 @@ module Ably
|
|
67
67
|
|
68
68
|
# Creates a {Ably::Rest::Client Rest Client} and configures the {Ably::Auth} object for the connection.
|
69
69
|
#
|
70
|
-
# @param [Hash,String] options an options Hash used to configure the client and the authentication, or String with an API key
|
70
|
+
# @param [Hash,String] options an options Hash used to configure the client and the authentication, or String with an API key or Token ID
|
71
71
|
# @option options (see Ably::Auth#authorise)
|
72
72
|
# @option options [Boolean] :tls TLS is used by default, providing a value of false disables TLS. Please note Basic Auth is disallowed without TLS as secrets cannot be transmitted over unsecured connections.
|
73
73
|
# @option options [String] :api_key API key comprising the key ID and key secret in a single string
|
@@ -96,7 +96,11 @@ module Ably
|
|
96
96
|
|
97
97
|
options = options.clone
|
98
98
|
if options.kind_of?(String)
|
99
|
-
options =
|
99
|
+
options = if options.match(/^[\w]{2,}\.[\w]{2,}:[\w]{2,}$/)
|
100
|
+
{ api_key: options }
|
101
|
+
else
|
102
|
+
{ token_id: options }
|
103
|
+
end
|
100
104
|
end
|
101
105
|
|
102
106
|
@tls = options.delete(:tls) == false ? false : true
|
@@ -83,7 +83,7 @@ module Ably
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def decode_message(presence_message)
|
86
|
-
presence_message.decode
|
86
|
+
presence_message.decode channel
|
87
87
|
rescue Ably::Exceptions::CipherError, Ably::Exceptions::EncoderError => e
|
88
88
|
client.logger.error "Decoding Error on presence channel '#{channel.name}', presence message client_id '#{presence_message.client_id}'. #{e.class.name}: #{e.message}"
|
89
89
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ably/modules/event_emitter.rb'
|
2
|
+
|
1
3
|
module Ably::Util
|
2
4
|
# PubSub class provides methods to publish & subscribe to events, with methods and naming
|
3
5
|
# intentionally different to EventEmitter as it is intended for private message handling
|
@@ -34,7 +36,7 @@ module Ably::Util
|
|
34
36
|
self.class.instance_eval do
|
35
37
|
configure_event_emitter options
|
36
38
|
|
37
|
-
alias_method :subscribe, :
|
39
|
+
alias_method :subscribe, :unsafe_on
|
38
40
|
alias_method :publish, :trigger
|
39
41
|
alias_method :unsubscribe, :off
|
40
42
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ably::Util
|
2
|
+
# SafeDeferrable class provides a Deferrable that is safe to use for for public interfaces
|
3
|
+
# of this client library. Any exceptions raised in the success or failure callbacks is
|
4
|
+
# caught and logged to the provided logger.
|
5
|
+
#
|
6
|
+
# An exception in a callback provided by a developer should not break this client library
|
7
|
+
# and stop further execution of code.
|
8
|
+
#
|
9
|
+
class SafeDeferrable
|
10
|
+
include Ably::Modules::SafeDeferrable
|
11
|
+
|
12
|
+
attr_reader :logger
|
13
|
+
|
14
|
+
def initialize(logger)
|
15
|
+
@logger = logger
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|