ably 0.1.6 → 0.2.0
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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +8 -1
- data/Rakefile +10 -0
- data/ably.gemspec +18 -18
- data/lib/ably.rb +6 -5
- data/lib/ably/auth.rb +11 -14
- data/lib/ably/exceptions.rb +18 -15
- data/lib/ably/logger.rb +102 -0
- data/lib/ably/models/error_info.rb +1 -1
- data/lib/ably/models/message.rb +19 -5
- data/lib/ably/models/message_encoders/base.rb +107 -0
- data/lib/ably/models/message_encoders/base64.rb +39 -0
- data/lib/ably/models/message_encoders/cipher.rb +80 -0
- data/lib/ably/models/message_encoders/json.rb +33 -0
- data/lib/ably/models/message_encoders/utf8.rb +33 -0
- data/lib/ably/models/paginated_resource.rb +23 -6
- data/lib/ably/models/presence_message.rb +19 -7
- data/lib/ably/models/protocol_message.rb +5 -4
- data/lib/ably/models/token.rb +2 -2
- data/lib/ably/modules/channels_collection.rb +0 -3
- data/lib/ably/modules/conversions.rb +3 -3
- data/lib/ably/modules/encodeable.rb +68 -0
- data/lib/ably/modules/event_emitter.rb +10 -4
- data/lib/ably/modules/event_machine_helpers.rb +6 -4
- data/lib/ably/modules/http_helpers.rb +7 -2
- data/lib/ably/modules/model_common.rb +2 -0
- data/lib/ably/modules/state_emitter.rb +10 -1
- data/lib/ably/realtime.rb +19 -12
- data/lib/ably/realtime/channel.rb +26 -13
- data/lib/ably/realtime/client.rb +31 -7
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -3
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +13 -4
- data/lib/ably/realtime/connection.rb +152 -46
- data/lib/ably/realtime/connection/connection_manager.rb +168 -0
- data/lib/ably/realtime/connection/connection_state_machine.rb +56 -33
- data/lib/ably/realtime/connection/websocket_transport.rb +56 -29
- data/lib/ably/{models → realtime/models}/nil_channel.rb +1 -1
- data/lib/ably/realtime/presence.rb +38 -13
- data/lib/ably/rest.rb +7 -5
- data/lib/ably/rest/channel.rb +24 -3
- data/lib/ably/rest/client.rb +56 -17
- data/lib/ably/rest/middleware/encoder.rb +49 -0
- data/lib/ably/rest/middleware/exceptions.rb +3 -2
- data/lib/ably/rest/middleware/logger.rb +37 -0
- data/lib/ably/rest/presence.rb +10 -2
- data/lib/ably/util/crypto.rb +57 -29
- data/lib/ably/util/pub_sub.rb +11 -0
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_spec.rb +65 -7
- data/spec/acceptance/realtime/connection_spec.rb +123 -27
- data/spec/acceptance/realtime/message_spec.rb +319 -34
- data/spec/acceptance/realtime/presence_history_spec.rb +58 -0
- data/spec/acceptance/realtime/presence_spec.rb +160 -18
- data/spec/acceptance/rest/auth_spec.rb +93 -49
- data/spec/acceptance/rest/base_spec.rb +10 -10
- data/spec/acceptance/rest/channel_spec.rb +35 -19
- data/spec/acceptance/rest/channels_spec.rb +8 -8
- data/spec/acceptance/rest/message_spec.rb +224 -0
- data/spec/acceptance/rest/presence_spec.rb +159 -23
- data/spec/acceptance/rest/stats_spec.rb +5 -5
- data/spec/acceptance/rest/time_spec.rb +4 -4
- data/spec/integration/rest/auth.rb +1 -1
- data/spec/resources/crypto-data-128.json +56 -0
- data/spec/resources/crypto-data-256.json +56 -0
- data/spec/rspec_config.rb +39 -0
- data/spec/spec_helper.rb +4 -42
- data/spec/support/api_helper.rb +1 -1
- data/spec/support/event_machine_helper.rb +0 -5
- data/spec/support/protocol_msgbus_helper.rb +3 -3
- data/spec/support/test_app.rb +3 -3
- data/spec/unit/logger_spec.rb +135 -0
- data/spec/unit/models/message_encoders/base64_spec.rb +181 -0
- data/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
- data/spec/unit/models/message_encoders/json_spec.rb +135 -0
- data/spec/unit/models/message_encoders/utf8_spec.rb +100 -0
- data/spec/unit/models/message_spec.rb +16 -1
- data/spec/unit/models/paginated_resource_spec.rb +46 -0
- data/spec/unit/models/presence_message_spec.rb +18 -5
- data/spec/unit/models/token_spec.rb +1 -1
- data/spec/unit/modules/event_emitter_spec.rb +24 -10
- data/spec/unit/realtime/channel_spec.rb +3 -3
- data/spec/unit/realtime/channels_spec.rb +1 -1
- data/spec/unit/realtime/client_spec.rb +44 -2
- data/spec/unit/realtime/connection_spec.rb +2 -2
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +4 -4
- data/spec/unit/realtime/presence_spec.rb +1 -1
- data/spec/unit/realtime/realtime_spec.rb +3 -3
- data/spec/unit/realtime/websocket_transport_spec.rb +24 -0
- data/spec/unit/rest/channels_spec.rb +1 -1
- data/spec/unit/rest/client_spec.rb +45 -10
- data/spec/unit/util/crypto_spec.rb +82 -0
- data/spec/unit/{modules → util}/pub_sub_spec.rb +13 -1
- metadata +43 -12
- data/spec/acceptance/crypto.rb +0 -63
@@ -5,13 +5,28 @@ module Ably::Realtime
|
|
5
5
|
module StatesmanMonkeyPatch
|
6
6
|
# Override Statesman's #before_transition to support :from arrays
|
7
7
|
# This can be removed once https://github.com/gocardless/statesman/issues/95 is solved
|
8
|
-
def before_transition(options, &block)
|
9
|
-
|
8
|
+
def before_transition(options = nil, &block)
|
9
|
+
arrayify_transition(options) do |options_without_from_array|
|
10
|
+
super *options_without_from_array, &block
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_transition(options = nil, &block)
|
15
|
+
arrayify_transition(options) do |options_without_from_array|
|
16
|
+
super *options_without_from_array, &block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def arrayify_transition(options, &block)
|
22
|
+
if options.nil?
|
23
|
+
yield []
|
24
|
+
elsif options.fetch(:from, nil).kind_of?(Array)
|
10
25
|
options[:from].each do |from_state|
|
11
|
-
|
26
|
+
yield [options.merge(from: from_state)]
|
12
27
|
end
|
13
28
|
else
|
14
|
-
|
29
|
+
yield [options]
|
15
30
|
end
|
16
31
|
end
|
17
32
|
end
|
@@ -34,59 +49,63 @@ module Ably::Realtime
|
|
34
49
|
end
|
35
50
|
|
36
51
|
transition :from => :initialized, :to => [:connecting, :closed]
|
37
|
-
transition :from => :connecting, :to => [:connected, :failed, :closed]
|
52
|
+
transition :from => :connecting, :to => [:connected, :failed, :closed, :disconnected]
|
38
53
|
transition :from => :connected, :to => [:disconnected, :suspended, :closed, :failed]
|
39
|
-
transition :from => :disconnected, :to => [:connecting, :closed]
|
40
|
-
transition :from => :suspended, :to => [:connecting, :closed]
|
54
|
+
transition :from => :disconnected, :to => [:connecting, :closed, :failed]
|
55
|
+
transition :from => :suspended, :to => [:connecting, :closed, :failed]
|
41
56
|
transition :from => :closed, :to => [:connecting]
|
42
57
|
transition :from => :failed, :to => [:connecting]
|
43
58
|
|
44
|
-
|
45
|
-
connection.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
59
|
+
after_transition do |connection, transition|
|
60
|
+
connection.synchronize_state_with_statemachine
|
61
|
+
end
|
62
|
+
|
63
|
+
after_transition(to: [:connecting], from: [:initialized, :closed, :failed]) do |connection|
|
64
|
+
connection.manager.setup_transport
|
65
|
+
end
|
66
|
+
|
67
|
+
after_transition(to: [:connecting], from: [:disconnected, :suspended]) do |connection|
|
68
|
+
connection.manager.reconnect_transport
|
52
69
|
end
|
53
70
|
|
54
|
-
before_transition(to: [:
|
55
|
-
connection.
|
71
|
+
before_transition(to: [:connected]) do |connection|
|
72
|
+
connection.manager.cancel_connection_retry_timers
|
73
|
+
end
|
74
|
+
|
75
|
+
after_transition(to: [:disconnected], from: [:connecting]) do |connection, current_transition|
|
76
|
+
connection.manager.respond_to_transport_disconnected current_transition
|
56
77
|
end
|
57
78
|
|
58
79
|
after_transition(to: [:failed]) do |connection|
|
59
|
-
connection.
|
80
|
+
connection.manager.destroy_transport
|
60
81
|
end
|
61
82
|
|
62
83
|
before_transition(to: [:closed], from: [:initialized]) do |connection|
|
63
|
-
connection.
|
84
|
+
connection.manager.cancel_initialized_timers
|
64
85
|
end
|
65
86
|
|
66
87
|
before_transition(to: [:closed], from: [:connecting, :connected, :disconnected, :suspended]) do |connection|
|
67
|
-
connection.
|
68
|
-
connection.transport.disconnect
|
88
|
+
connection.manager.close_connection
|
69
89
|
end
|
70
90
|
|
71
|
-
|
72
|
-
|
91
|
+
# Override Statesman's #transition_to so that:
|
92
|
+
# * log state change failures to {Logger}
|
93
|
+
def transition_to(state, *args)
|
94
|
+
unless result = super(state, *args)
|
95
|
+
logger.fatal "ConnectionStateMachine: Unable to transition from #{current_state} => #{state}"
|
96
|
+
end
|
97
|
+
result
|
73
98
|
end
|
74
99
|
|
75
|
-
def
|
76
|
-
|
77
|
-
super(connection)
|
100
|
+
def previous_transition
|
101
|
+
history[-2]
|
78
102
|
end
|
79
103
|
|
80
|
-
|
81
|
-
|
82
|
-
unless super(*args)
|
83
|
-
logger.debug "Unable to transition to #{args[0]} from #{current_state}"
|
84
|
-
end
|
104
|
+
def previous_state
|
105
|
+
previous_transition.to_state if previous_transition
|
85
106
|
end
|
86
107
|
|
87
108
|
private
|
88
|
-
attr_reader :connection
|
89
|
-
|
90
109
|
# TODO: Implement once CLOSED ProtocolMessage is sent back from Ably in response to a CLOSE message
|
91
110
|
#
|
92
111
|
# FORCE_CONNECTION_CLOSED_TIMEOUT = 5
|
@@ -103,6 +122,10 @@ module Ably::Realtime
|
|
103
122
|
# end.clear
|
104
123
|
# end
|
105
124
|
|
125
|
+
def connection
|
126
|
+
object
|
127
|
+
end
|
128
|
+
|
106
129
|
def logger
|
107
130
|
connection.logger
|
108
131
|
end
|
@@ -4,7 +4,6 @@ module Ably::Realtime
|
|
4
4
|
# @api private
|
5
5
|
class WebsocketTransport < EventMachine::Connection
|
6
6
|
include Ably::Modules::EventEmitter
|
7
|
-
include Ably::Modules::Conversions
|
8
7
|
extend Ably::Modules::Enum
|
9
8
|
|
10
9
|
# Valid WebSocket connection states
|
@@ -17,28 +16,17 @@ module Ably::Realtime
|
|
17
16
|
)
|
18
17
|
include Ably::Modules::StateEmitter
|
19
18
|
|
20
|
-
def initialize(connection)
|
19
|
+
def initialize(connection, url)
|
21
20
|
@connection = connection
|
22
21
|
@state = STATE.Initialized
|
23
|
-
|
22
|
+
@url = url
|
24
23
|
|
25
|
-
|
26
|
-
# @param [Object] object to serialize and send to the WebSocket driver
|
27
|
-
# @api public
|
28
|
-
def send_object(object)
|
29
|
-
case client.protocol
|
30
|
-
when :json
|
31
|
-
driver.text(object.to_json)
|
32
|
-
when :msgpack
|
33
|
-
driver.binary(object.to_msgpack.unpack('c*'))
|
34
|
-
else
|
35
|
-
client.logger.error "Unsupported protocol '#{client.protocol}' for serialization, object cannot be serialized and sent to Ably over this WebSocket"
|
36
|
-
end
|
24
|
+
setup_event_handlers
|
37
25
|
end
|
38
26
|
|
39
27
|
# Disconnect the socket transport connection and write all pending text.
|
40
28
|
# If Disconnected state is not automatically triggered, it will be triggered automatically
|
41
|
-
# @return
|
29
|
+
# @return [void]
|
42
30
|
# @api public
|
43
31
|
def disconnect
|
44
32
|
close_connection_after_writing
|
@@ -81,13 +69,7 @@ module Ably::Realtime
|
|
81
69
|
# URL end point including initialization configuration
|
82
70
|
# {http://www.rubydoc.info/gems/websocket-driver/0.3.5/WebSocket/Driver WebSocket::Driver} interface
|
83
71
|
def url
|
84
|
-
|
85
|
-
endpoint.query = URI.encode_www_form(client.auth.auth_params.merge(
|
86
|
-
timestamp: as_since_epoch(Time.now),
|
87
|
-
format: client.protocol,
|
88
|
-
echo: client.echo_messages
|
89
|
-
))
|
90
|
-
end.to_s
|
72
|
+
@url
|
91
73
|
end
|
92
74
|
|
93
75
|
# {http://www.rubydoc.info/gems/websocket-driver/0.3.5/WebSocket/Driver WebSocket::Driver} interface
|
@@ -101,9 +83,44 @@ module Ably::Realtime
|
|
101
83
|
!connecting? && !connected?
|
102
84
|
end
|
103
85
|
|
86
|
+
# @!attribute [r] __incoming_protocol_msgbus__
|
87
|
+
# @return [Ably::Util::PubSub] Websocket Transport internal incoming protocol message bus
|
88
|
+
# @api private
|
89
|
+
def __incoming_protocol_msgbus__
|
90
|
+
@__incoming_protocol_msgbus__ ||= create_pub_sub_message_bus
|
91
|
+
end
|
92
|
+
|
93
|
+
# @!attribute [r] __outgoing_protocol_msgbus__
|
94
|
+
# @return [Ably::Util::PubSub] Websocket Transport internal outgoing protocol message bus
|
95
|
+
# @api private
|
96
|
+
def __outgoing_protocol_msgbus__
|
97
|
+
@__outgoing_protocol_msgbus__ ||= create_pub_sub_message_bus
|
98
|
+
end
|
99
|
+
|
104
100
|
private
|
105
101
|
attr_reader :connection, :driver
|
106
102
|
|
103
|
+
# Send object down the WebSocket driver connection as a serialized string/byte array based on protocol
|
104
|
+
# @param [Object] object to serialize and send to the WebSocket driver
|
105
|
+
# @api public
|
106
|
+
def send_object(object)
|
107
|
+
case client.protocol
|
108
|
+
when :json
|
109
|
+
driver.text(object.to_json)
|
110
|
+
when :msgpack
|
111
|
+
driver.binary(object.to_msgpack.unpack('C*'))
|
112
|
+
else
|
113
|
+
client.logger.fatal "WebsocketTransport: Unsupported protocol '#{client.protocol}' for serialization, object cannot be serialized and sent to Ably over this WebSocket"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def setup_event_handlers
|
118
|
+
__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
119
|
+
send_object protocol_message
|
120
|
+
client.logger.debug "WebsocketTransport: Prot msg sent =>: #{protocol_message.action} #{protocol_message}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
107
124
|
def clear_timer
|
108
125
|
if @timer
|
109
126
|
@timer.cancel
|
@@ -121,17 +138,18 @@ module Ably::Realtime
|
|
121
138
|
@driver = WebSocket::Driver.client(self)
|
122
139
|
|
123
140
|
driver.on("open") do
|
124
|
-
logger.debug "
|
141
|
+
logger.debug "WebsocketTransport: socket opened to #{url}, waiting for Connected protocol message"
|
125
142
|
end
|
126
143
|
|
127
144
|
driver.on("message") do |event|
|
128
145
|
event_data = parse_event_data(event.data).freeze
|
129
146
|
protocol_message = Ably::Models::ProtocolMessage.new(event_data)
|
130
|
-
logger.debug "Prot msg recv <=: #{protocol_message.action} #{event_data}"
|
147
|
+
logger.debug "WebsocketTransport: Prot msg recv <=: #{protocol_message.action} #{event_data}"
|
148
|
+
|
131
149
|
if protocol_message.invalid?
|
132
|
-
logger.
|
150
|
+
logger.fatal "WebsocketTransport: Invalid Protocol Message received: #{event_data}\nNo action taken"
|
133
151
|
else
|
134
|
-
|
152
|
+
__incoming_protocol_msgbus__.publish :protocol_message, protocol_message
|
135
153
|
end
|
136
154
|
end
|
137
155
|
end
|
@@ -150,12 +168,21 @@ module Ably::Realtime
|
|
150
168
|
when :json
|
151
169
|
JSON.parse(data)
|
152
170
|
when :msgpack
|
153
|
-
MessagePack.unpack(data.pack('
|
171
|
+
MessagePack.unpack(data.pack('C*'))
|
154
172
|
else
|
155
|
-
client.logger.
|
173
|
+
client.logger.fatal "WebsocketTransport: Unsupported Protocol Message format #{client.protocol}"
|
156
174
|
data
|
157
175
|
end
|
158
176
|
end
|
177
|
+
|
178
|
+
def create_pub_sub_message_bus
|
179
|
+
Ably::Util::PubSub.new(
|
180
|
+
coerce_into: Proc.new do |event|
|
181
|
+
raise KeyError, "Expected :protocol_message, :#{event} is disallowed" unless event == :protocol_message
|
182
|
+
:protocol_message
|
183
|
+
end
|
184
|
+
)
|
185
|
+
end
|
159
186
|
end
|
160
187
|
end
|
161
188
|
end
|
@@ -17,13 +17,19 @@ module Ably::Realtime
|
|
17
17
|
# {Ably::Realtime::Channel} this Presence object is assoicated with
|
18
18
|
attr_reader :channel
|
19
19
|
|
20
|
+
# A unique member identifier for this channel client, disambiguating situations where a given
|
21
|
+
# client_id is present on multiple connections simultaneously.
|
22
|
+
# TODO: This does not work at present as no ACK is sent from the server with a memberId
|
23
|
+
attr_reader :member_id
|
24
|
+
|
20
25
|
def initialize(channel)
|
21
26
|
@channel = channel
|
22
27
|
@state = STATE.Initialized
|
23
28
|
@members = Hash.new
|
24
29
|
@subscriptions = Hash.new { |hash, key| hash[key] = [] }
|
25
30
|
@client_id = client.client_id
|
26
|
-
@
|
31
|
+
@data = nil
|
32
|
+
@member_id = nil
|
27
33
|
|
28
34
|
setup_event_handlers
|
29
35
|
end
|
@@ -31,17 +37,17 @@ module Ably::Realtime
|
|
31
37
|
# Enter this client into this channel. This client will be added to the presence set
|
32
38
|
# and presence subscribers will see an enter message for this client.
|
33
39
|
# @param [Hash,String] options an options Hash to specify client data and/or client ID, or a String with the client data
|
34
|
-
# @option options [String] :
|
40
|
+
# @option options [String] :data optional data (eg a status message) for this member
|
35
41
|
# @option options [String] :client_id the optional id of the client.
|
36
42
|
# This option is provided to support connections from server instances that act on behalf of
|
37
43
|
# multiple client_ids. In order to be able to enter the channel with this method, the client
|
38
44
|
# library must have been instanced either with a key, or with a token bound to the wildcard clientId.
|
39
45
|
# @yield [Ably::Realtime::Presence] On success, will call the block with the {Ably::Realtime::Presence}
|
40
|
-
# @return [Ably::
|
46
|
+
# @return [Ably::Models::PresenceMessage] Deferrable {Ably::Models::PresenceMessage} that supports both success (callback) and failure (errback) callbacks
|
41
47
|
#
|
42
48
|
def enter(options = {}, &blk)
|
43
|
-
@client_id
|
44
|
-
@
|
49
|
+
@client_id = options.fetch(:client_id, client_id)
|
50
|
+
@data = options.fetch(:data, data)
|
45
51
|
|
46
52
|
raise Ably::Exceptions::Standard.new('Unable to enter presence channel without a client_id', 400, 91000) unless client_id
|
47
53
|
|
@@ -57,7 +63,7 @@ module Ably::Realtime
|
|
57
63
|
change_state STATE.Entering
|
58
64
|
send_presence_protocol_message(Ably::Models::PresenceMessage::ACTION.Enter).tap do |deferrable|
|
59
65
|
deferrable.errback { |message, error| change_state STATE.Failed, error }
|
60
|
-
deferrable.callback { |message| change_state STATE.Entered }
|
66
|
+
deferrable.callback { |message| change_state STATE.Entered, message }
|
61
67
|
end
|
62
68
|
end
|
63
69
|
end
|
@@ -72,7 +78,7 @@ module Ably::Realtime
|
|
72
78
|
def leave(options = {}, &blk)
|
73
79
|
raise Ably::Exceptions::Standard.new('Unable to leave presence channel that is not entered', 400, 91002) unless ably_to_leave?
|
74
80
|
|
75
|
-
@
|
81
|
+
@data = options.fetch(:data, data)
|
76
82
|
|
77
83
|
if state == STATE.Left
|
78
84
|
blk.call self if block_given?
|
@@ -100,12 +106,12 @@ module Ably::Realtime
|
|
100
106
|
# @return (see Presence#enter)
|
101
107
|
#
|
102
108
|
def update(options = {}, &blk)
|
103
|
-
@
|
109
|
+
@data = options.fetch(:data, data)
|
104
110
|
|
105
111
|
ensure_channel_attached do
|
106
112
|
send_presence_protocol_message(Ably::Models::PresenceMessage::ACTION.Update).tap do |deferrable|
|
107
113
|
deferrable.callback do |message|
|
108
|
-
change_state STATE.Entered unless entered?
|
114
|
+
change_state STATE.Entered, message unless entered?
|
109
115
|
blk.call self if block_given?
|
110
116
|
end
|
111
117
|
end
|
@@ -148,6 +154,14 @@ module Ably::Realtime
|
|
148
154
|
end
|
149
155
|
end
|
150
156
|
|
157
|
+
# Return the presence messages history for the channel
|
158
|
+
#
|
159
|
+
# @param (see Ably::Rest::Presence#history)
|
160
|
+
# @option options (see Ably::Rest::Presence#history)
|
161
|
+
def history(options = {})
|
162
|
+
rest_presence.history(options)
|
163
|
+
end
|
164
|
+
|
151
165
|
# @!attribute [r] __incoming_msgbus__
|
152
166
|
# @return [Ably::Util::PubSub] Client library internal channel incoming message bus
|
153
167
|
# @api private
|
@@ -158,7 +172,7 @@ module Ably::Realtime
|
|
158
172
|
end
|
159
173
|
|
160
174
|
private
|
161
|
-
attr_reader :members, :subscriptions, :client_id, :
|
175
|
+
attr_reader :members, :subscriptions, :client_id, :data
|
162
176
|
|
163
177
|
def ably_to_leave?
|
164
178
|
entering? || entered?
|
@@ -166,7 +180,9 @@ module Ably::Realtime
|
|
166
180
|
|
167
181
|
def setup_event_handlers
|
168
182
|
__incoming_msgbus__.subscribe(:presence) do |presence|
|
183
|
+
presence.decode self.channel
|
169
184
|
update_members_from_presence_message presence
|
185
|
+
|
170
186
|
subscriptions[:all].each { |cb| cb.call(presence) }
|
171
187
|
subscriptions[presence.action].each { |cb| cb.call(presence) }
|
172
188
|
end
|
@@ -182,6 +198,10 @@ module Ably::Realtime
|
|
182
198
|
channel.on(Channel::STATE.Failed) do
|
183
199
|
change_state STATE.Failed unless left? || initialized?
|
184
200
|
end
|
201
|
+
|
202
|
+
on(STATE.Entered) do |message|
|
203
|
+
@member_id = message.member_id
|
204
|
+
end
|
185
205
|
end
|
186
206
|
|
187
207
|
# @return [Ably::Models::PresenceMessage] presence message is returned allowing callbacks to be added
|
@@ -207,9 +227,11 @@ module Ably::Realtime
|
|
207
227
|
action: Ably::Models::PresenceMessage.ACTION(action).to_i,
|
208
228
|
clientId: client_id,
|
209
229
|
}
|
210
|
-
model.merge!(
|
230
|
+
model.merge!(data: data) if data
|
211
231
|
|
212
|
-
Ably::Models::PresenceMessage.new(model, nil)
|
232
|
+
Ably::Models::PresenceMessage.new(model, nil).tap do |presence_message|
|
233
|
+
presence_message.encode self.channel
|
234
|
+
end
|
213
235
|
end
|
214
236
|
|
215
237
|
def update_members_from_presence_message(presence_message)
|
@@ -253,7 +275,10 @@ module Ably::Realtime
|
|
253
275
|
channel.client
|
254
276
|
end
|
255
277
|
|
256
|
-
|
278
|
+
def rest_presence
|
279
|
+
client.rest_client.channel(channel.name).presence
|
280
|
+
end
|
281
|
+
|
257
282
|
# Used by {Ably::Modules::StateEmitter} to debug action changes
|
258
283
|
def logger
|
259
284
|
client.logger
|
data/lib/ably/rest.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'ably/rest/channel'
|
2
|
+
require 'ably/rest/channels'
|
3
|
+
require 'ably/rest/client'
|
4
|
+
require 'ably/rest/presence'
|
5
5
|
|
6
|
-
Dir.glob(File.expand_path("
|
6
|
+
Dir.glob(File.expand_path("models/*.rb", File.dirname(__FILE__))).each do |file|
|
7
7
|
require file
|
8
8
|
end
|
9
9
|
|
10
|
+
require 'ably/models/message_encoders/base'
|
11
|
+
|
10
12
|
module Ably
|
11
13
|
# Rest provides the top-level class to be instanced for the Ably Rest library
|
12
14
|
#
|