ably 0.7.0 → 0.7.1
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.
- data/.travis.yml +2 -2
- data/Rakefile +2 -0
- data/SPEC.md +230 -194
- data/ably.gemspec +2 -0
- data/lib/ably/auth.rb +7 -5
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +5 -7
- data/lib/ably/models/paginated_resource.rb +14 -21
- data/lib/ably/models/protocol_message.rb +1 -1
- data/lib/ably/modules/ably.rb +4 -0
- data/lib/ably/modules/async_wrapper.rb +2 -2
- data/lib/ably/modules/channels_collection.rb +31 -8
- data/lib/ably/modules/conversions.rb +10 -0
- data/lib/ably/modules/enum.rb +2 -3
- data/lib/ably/modules/state_emitter.rb +8 -8
- data/lib/ably/modules/state_machine.rb +7 -3
- data/lib/ably/realtime/channel.rb +6 -5
- data/lib/ably/realtime/channel/channel_manager.rb +11 -10
- data/lib/ably/realtime/channel/channel_state_machine.rb +10 -9
- data/lib/ably/realtime/channels.rb +3 -0
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/ably/realtime/connection.rb +55 -16
- data/lib/ably/realtime/connection/connection_manager.rb +25 -8
- data/lib/ably/realtime/connection/connection_state_machine.rb +9 -9
- data/lib/ably/realtime/connection/websocket_transport.rb +2 -2
- data/lib/ably/realtime/presence.rb +16 -17
- data/lib/ably/util/crypto.rb +1 -1
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +6 -5
- data/spec/acceptance/realtime/connection_failures_spec.rb +103 -27
- data/spec/acceptance/realtime/connection_spec.rb +81 -17
- data/spec/acceptance/realtime/presence_spec.rb +82 -30
- data/spec/acceptance/rest/auth_spec.rb +22 -19
- data/spec/acceptance/rest/client_spec.rb +4 -4
- data/spec/acceptance/rest/presence_spec.rb +12 -6
- data/spec/rspec_config.rb +9 -0
- data/spec/shared/model_behaviour.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/support/event_machine_helper.rb +26 -37
- data/spec/support/markdown_spec_formatter.rb +96 -68
- data/spec/support/rest_testapp_before_retry.rb +15 -0
- data/spec/support/test_app.rb +4 -0
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +20 -2
- data/spec/unit/models/message_spec.rb +1 -1
- data/spec/unit/models/paginated_resource_spec.rb +15 -1
- data/spec/unit/modules/enum_spec.rb +10 -0
- data/spec/unit/realtime/channels_spec.rb +30 -0
- data/spec/unit/rest/channels_spec.rb +30 -0
- metadata +101 -35
- checksums.yaml +0 -7
@@ -15,6 +15,7 @@ module Ably
|
|
15
15
|
# @param name [String] The name of the channel
|
16
16
|
# @param channel_options [Hash] Channel options, currently reserved for Encryption options
|
17
17
|
# @return [Ably::Realtime::Channel}
|
18
|
+
#
|
18
19
|
def get(*args)
|
19
20
|
super
|
20
21
|
end
|
@@ -27,6 +28,7 @@ module Ably
|
|
27
28
|
# @yield [options] (optional) if a missing_block is passed to this method and no channel exists matching the name, this block is called
|
28
29
|
# @yieldparam [String] name of the missing channel
|
29
30
|
# @return [Ably::Realtime::Channel]
|
31
|
+
#
|
30
32
|
def fetch(*args)
|
31
33
|
super
|
32
34
|
end
|
@@ -37,6 +39,7 @@ module Ably
|
|
37
39
|
# the memory footprint of the {Ably::Realtime::Channel Realtime Channel object}. Release channels to free up resources if required
|
38
40
|
#
|
39
41
|
# @return [void]
|
42
|
+
#
|
40
43
|
def release(channel)
|
41
44
|
get(channel).detach do
|
42
45
|
@channels.delete(channel)
|
@@ -54,7 +54,7 @@ module Ably::Realtime
|
|
54
54
|
|
55
55
|
when ACTION.Connect
|
56
56
|
when ACTION.Connected
|
57
|
-
connection.transition_state_machine :connected
|
57
|
+
connection.transition_state_machine :connected, protocol_message.error
|
58
58
|
|
59
59
|
when ACTION.Disconnect, ACTION.Disconnected
|
60
60
|
connection.transition_state_machine :disconnected, protocol_message.error
|
@@ -118,6 +118,7 @@ module Ably::Realtime
|
|
118
118
|
def update_connection_recovery_info(protocol_message)
|
119
119
|
if protocol_message.connection_key && (protocol_message.connection_key != connection.key)
|
120
120
|
logger.debug "New connection ID set to #{protocol_message.connection_id} with connection key #{protocol_message.connection_key}"
|
121
|
+
detach_attached_channels protocol_message.error if protocol_message.error
|
121
122
|
connection.update_connection_id_and_key protocol_message.connection_id, protocol_message.connection_key
|
122
123
|
end
|
123
124
|
|
@@ -126,6 +127,15 @@ module Ably::Realtime
|
|
126
127
|
end
|
127
128
|
end
|
128
129
|
|
130
|
+
def detach_attached_channels(error)
|
131
|
+
channels.select do |channel|
|
132
|
+
channel.attached? || channel.attaching?
|
133
|
+
end.each do |channel|
|
134
|
+
logger.warn "Detaching channel '#{channel.name}': #{error}"
|
135
|
+
channel.manager.suspend error
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
129
139
|
def ack_pending_queue_for_message_serial(ack_protocol_message)
|
130
140
|
drop_pending_queue_from_ack(ack_protocol_message) do |protocol_message|
|
131
141
|
ack_messages protocol_message.messages
|
@@ -156,7 +156,7 @@ module Ably
|
|
156
156
|
#
|
157
157
|
# @return [void]
|
158
158
|
#
|
159
|
-
def ping
|
159
|
+
def ping
|
160
160
|
raise RuntimeError, 'Cannot send a ping when connection is not open' if initialized?
|
161
161
|
raise RuntimeError, 'Cannot send a ping when connection is in a closed or failed state' if closed? || failed?
|
162
162
|
|
@@ -166,7 +166,7 @@ module Ably
|
|
166
166
|
if protocol_message.action == Ably::Models::ProtocolMessage::ACTION.Heartbeat
|
167
167
|
__incoming_protocol_msgbus__.unsubscribe(:protocol_message, &wait_for_ping)
|
168
168
|
time_passed = (Time.now.to_f * 1000 - started.to_f * 1000).to_i
|
169
|
-
|
169
|
+
yield time_passed if block_given?
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
@@ -177,6 +177,25 @@ module Ably
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
# @yield [Boolean] True if an internet connection check appears to be up following an HTTP request to a reliable CDN
|
181
|
+
# @return [EventMachine::Deferrable]
|
182
|
+
# @api private
|
183
|
+
def internet_up?
|
184
|
+
EventMachine::DefaultDeferrable.new.tap do |deferrable|
|
185
|
+
EventMachine::HttpRequest.new(Ably::INTERNET_CHECK.fetch(:url)).get.tap do |http|
|
186
|
+
http.errback do
|
187
|
+
yield false if block_given?
|
188
|
+
deferrable.fail
|
189
|
+
end
|
190
|
+
http.callback do
|
191
|
+
result = http.response_header.status == 200 && http.response.strip == Ably::INTERNET_CHECK.fetch(:ok_text)
|
192
|
+
yield result if block_given?
|
193
|
+
deferrable.succeed
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
180
199
|
# @!attribute [r] recovery_key
|
181
200
|
# @return [String] recovery key that can be used by another client to recover this connection with the :recover option
|
182
201
|
def recovery_key
|
@@ -220,16 +239,31 @@ module Ably
|
|
220
239
|
@__incoming_protocol_msgbus__ ||= create_pub_sub_message_bus
|
221
240
|
end
|
222
241
|
|
223
|
-
#
|
224
|
-
# @
|
225
|
-
|
242
|
+
# Determines the correct host name to use for the next connection attempt and updates current_host
|
243
|
+
# @yield [String] The host name used for this connection, for network connection failures a {Ably::FALLBACK_HOSTS fallback host} is used to route around networking or intermittent problems if an Internet connection is available
|
244
|
+
# @api private
|
245
|
+
def determine_host
|
246
|
+
raise ArgumentError, 'Block required' unless block_given?
|
247
|
+
|
226
248
|
if can_use_fallback_hosts?
|
227
|
-
|
249
|
+
internet_up? do |internet_is_up_result|
|
250
|
+
@current_host = if internet_is_up_result
|
251
|
+
client.fallback_endpoint.host
|
252
|
+
else
|
253
|
+
client.endpoint.host
|
254
|
+
end
|
255
|
+
yield current_host
|
256
|
+
end
|
228
257
|
else
|
229
|
-
client.endpoint.host
|
258
|
+
@current_host = client.endpoint.host
|
259
|
+
yield current_host
|
230
260
|
end
|
231
261
|
end
|
232
262
|
|
263
|
+
# @return [String] The current host that is configured following a call to method {#determine_host}
|
264
|
+
# @api private
|
265
|
+
attr_reader :current_host
|
266
|
+
|
233
267
|
# @!attribute [r] port
|
234
268
|
# @return [Integer] The default port used for this connection
|
235
269
|
def port
|
@@ -270,8 +304,10 @@ module Ably
|
|
270
304
|
end
|
271
305
|
|
272
306
|
# @api private
|
273
|
-
def create_websocket_transport
|
274
|
-
|
307
|
+
def create_websocket_transport
|
308
|
+
raise ArgumentError, 'Block required' unless block_given?
|
309
|
+
|
310
|
+
blocking_operation = proc do
|
275
311
|
URI(client.endpoint).tap do |endpoint|
|
276
312
|
url_params = client.auth.auth_params.merge(
|
277
313
|
timestamp: as_since_epoch(Time.now),
|
@@ -295,17 +331,20 @@ module Ably
|
|
295
331
|
end
|
296
332
|
|
297
333
|
callback = proc do |url|
|
298
|
-
|
299
|
-
|
300
|
-
|
334
|
+
determine_host do |host|
|
335
|
+
begin
|
336
|
+
logger.debug "Connection: Opening socket connection to #{host}:#{port} and URL '#{url}'"
|
337
|
+
@transport = EventMachine.connect(host, port, WebsocketTransport, self, url) do |websocket_transport|
|
338
|
+
yield websocket_transport if block_given?
|
339
|
+
end
|
340
|
+
rescue EventMachine::ConnectionError => error
|
341
|
+
manager.connection_opening_failed error
|
301
342
|
end
|
302
|
-
rescue EventMachine::ConnectionError => error
|
303
|
-
manager.connection_opening_failed error
|
304
343
|
end
|
305
344
|
end
|
306
345
|
|
307
346
|
# client.auth.auth_params is a blocking call, so defer this into a thread
|
308
|
-
EventMachine.defer
|
347
|
+
EventMachine.defer blocking_operation, callback
|
309
348
|
end
|
310
349
|
|
311
350
|
# @api private
|
@@ -350,7 +389,7 @@ module Ably
|
|
350
389
|
end
|
351
390
|
|
352
391
|
# Simply wait until the next EventMachine tick to ensure Connection initialization is complete
|
353
|
-
def when_initialized
|
392
|
+
def when_initialized
|
354
393
|
EventMachine.next_tick { yield }
|
355
394
|
end
|
356
395
|
|
@@ -47,7 +47,7 @@ module Ably::Realtime
|
|
47
47
|
#
|
48
48
|
# @yield [Ably::Realtime::Connection::WebsocketTransport] block is called with new websocket transport
|
49
49
|
# @api private
|
50
|
-
def setup_transport
|
50
|
+
def setup_transport
|
51
51
|
if transport && !transport.ready_for_release?
|
52
52
|
raise RuntimeError, 'Existing WebsocketTransport is connected, and must be closed first'
|
53
53
|
end
|
@@ -57,14 +57,14 @@ module Ably::Realtime
|
|
57
57
|
return
|
58
58
|
end
|
59
59
|
|
60
|
-
logger.debug
|
60
|
+
logger.debug 'ConnectionManager: Opening a websocket transport connection'
|
61
61
|
|
62
62
|
connection.create_websocket_transport do |websocket_transport|
|
63
63
|
subscribe_to_transport_events websocket_transport
|
64
64
|
yield websocket_transport if block_given?
|
65
65
|
end
|
66
66
|
|
67
|
-
logger.debug
|
67
|
+
logger.debug "ConnectionManager: Setting up automatic connection timeout timer for #{TIMEOUTS.fetch(:open)}s"
|
68
68
|
create_timeout_timer_whilst_in_state(:connect, TIMEOUTS.fetch(:open)) do
|
69
69
|
connection_opening_failed Ably::Exceptions::ConnectionTimeoutError.new("Connection to Ably timed out after #{TIMEOUTS.fetch(:open)}s", nil, 80014)
|
70
70
|
end
|
@@ -74,10 +74,18 @@ module Ably::Realtime
|
|
74
74
|
#
|
75
75
|
# @api private
|
76
76
|
def connection_opening_failed(error)
|
77
|
-
logger.warn "ConnectionManager: Connection to #{connection.
|
77
|
+
logger.warn "ConnectionManager: Connection to #{connection.current_host}:#{connection.port} failed; #{error.message}"
|
78
78
|
connection.transition_state_machine next_retry_state, Ably::Exceptions::ConnectionError.new("Connection failed; #{error.message}", nil, 80000)
|
79
79
|
end
|
80
80
|
|
81
|
+
# Called whenever a new connection message is received with an error
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
def connected_with_error(error)
|
85
|
+
logger.warn "ConnectionManager: Connected with error; #{error.message}"
|
86
|
+
connection.trigger :error, error
|
87
|
+
end
|
88
|
+
|
81
89
|
# Ensures the underlying transport has been disconnected and all event emitter callbacks removed
|
82
90
|
#
|
83
91
|
# @api private
|
@@ -96,7 +104,7 @@ module Ably::Realtime
|
|
96
104
|
if !transport || transport.disconnected?
|
97
105
|
setup_transport
|
98
106
|
else
|
99
|
-
transport.reconnect connection.
|
107
|
+
transport.reconnect connection.current_host, connection.port
|
100
108
|
end
|
101
109
|
end
|
102
110
|
|
@@ -119,6 +127,15 @@ module Ably::Realtime
|
|
119
127
|
connection.transition_state_machine :closed
|
120
128
|
end
|
121
129
|
|
130
|
+
# Connection has failed
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
def fail(error)
|
134
|
+
connection.logger.fatal "ConnectionManager: Connection failed - #{error}"
|
135
|
+
connection.manager.destroy_transport
|
136
|
+
connection.once(:failed) { connection.trigger :error, error }
|
137
|
+
end
|
138
|
+
|
122
139
|
# When a connection is disconnected whilst connecting, attempt reconnect and/or set state to :suspended or :failed
|
123
140
|
#
|
124
141
|
# @api private
|
@@ -192,11 +209,11 @@ module Ably::Realtime
|
|
192
209
|
|
193
210
|
# Create a timer that will execute in timeout_in seconds.
|
194
211
|
# If the connection state changes however, cancel the timer
|
195
|
-
def create_timeout_timer_whilst_in_state(timer_id, timeout_in
|
196
|
-
raise 'Block required
|
212
|
+
def create_timeout_timer_whilst_in_state(timer_id, timeout_in)
|
213
|
+
raise ArgumentError, 'Block required' unless block_given?
|
197
214
|
|
198
215
|
timers[timer_id] << EventMachine::Timer.new(timeout_in) do
|
199
|
-
|
216
|
+
yield
|
200
217
|
end
|
201
218
|
connection.once_state_changed { clear_timers timer_id }
|
202
219
|
end
|
@@ -40,6 +40,10 @@ module Ably::Realtime
|
|
40
40
|
connection.manager.reconnect_transport
|
41
41
|
end
|
42
42
|
|
43
|
+
after_transition(to: [:connected]) do |connection, current_transition|
|
44
|
+
connection.manager.connected_with_error current_transition.metadata if current_transition.metadata
|
45
|
+
end
|
46
|
+
|
43
47
|
after_transition(to: [:disconnected, :suspended], from: [:connecting]) do |connection, current_transition|
|
44
48
|
connection.manager.respond_to_transport_disconnected_when_connecting current_transition
|
45
49
|
end
|
@@ -52,9 +56,8 @@ module Ably::Realtime
|
|
52
56
|
connection.manager.destroy_transport # never reuse a transport if the connection has failed
|
53
57
|
end
|
54
58
|
|
55
|
-
|
56
|
-
connection.
|
57
|
-
connection.manager.destroy_transport
|
59
|
+
before_transition(to: [:failed]) do |connection, current_transition|
|
60
|
+
connection.manager.fail current_transition.metadata
|
58
61
|
end
|
59
62
|
|
60
63
|
after_transition(to: [:closing], from: [:initialized, :disconnected, :suspended]) do |connection|
|
@@ -70,12 +73,9 @@ module Ably::Realtime
|
|
70
73
|
end
|
71
74
|
|
72
75
|
# Transitions responsible for updating connection#error_reason
|
73
|
-
before_transition(to: [:disconnected, :suspended, :failed]) do |connection, current_transition|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
before_transition(to: [:connected, :closed]) do |connection, current_transition|
|
78
|
-
connection.set_failed_connection_error_reason nil
|
76
|
+
before_transition(to: [:connected, :closed, :disconnected, :suspended, :failed]) do |connection, current_transition|
|
77
|
+
reason = current_transition.metadata if is_error_type?(current_transition.metadata)
|
78
|
+
connection.set_failed_connection_error_reason reason
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
@@ -57,7 +57,7 @@ module Ably::Realtime
|
|
57
57
|
#
|
58
58
|
def enter(options = {}, &success_block)
|
59
59
|
@client_id = options.fetch(:client_id, client_id)
|
60
|
-
@data = options.fetch(:data,
|
60
|
+
@data = options.fetch(:data, nil)
|
61
61
|
deferrable = EventMachine::DefaultDeferrable.new
|
62
62
|
|
63
63
|
raise Ably::Exceptions::Standard.new('Unable to enter presence channel without a client_id', 400, 91000) unless client_id
|
@@ -115,7 +115,7 @@ module Ably::Realtime
|
|
115
115
|
# @return (see Presence#enter)
|
116
116
|
#
|
117
117
|
def leave(options = {}, &success_block)
|
118
|
-
@data = options.fetch(:data)
|
118
|
+
@data = options.fetch(:data, data) # nil value defaults leave data to existing value
|
119
119
|
deferrable = EventMachine::DefaultDeferrable.new
|
120
120
|
|
121
121
|
raise Ably::Exceptions::Standard.new('Unable to leave presence channel that is not entered', 400, 91002) unless able_to_leave?
|
@@ -168,7 +168,7 @@ module Ably::Realtime
|
|
168
168
|
# @return (see Presence#enter)
|
169
169
|
#
|
170
170
|
def update(options = {}, &success_block)
|
171
|
-
@data = options.fetch(:data
|
171
|
+
@data = options.fetch(:data, nil)
|
172
172
|
deferrable = EventMachine::DefaultDeferrable.new
|
173
173
|
|
174
174
|
ensure_channel_attached(deferrable) do
|
@@ -211,9 +211,9 @@ module Ably::Realtime
|
|
211
211
|
#
|
212
212
|
# @yield [Array<Ably::Models::PresenceMessage>] array of members or the member
|
213
213
|
#
|
214
|
-
# @return [EventMachine::Deferrable] Deferrable that supports both success (callback) and failure (errback)
|
214
|
+
# @return [EventMachine::Deferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
|
215
215
|
#
|
216
|
-
def get(options = {}
|
216
|
+
def get(options = {})
|
217
217
|
wait_for_sync = options.fetch(:wait_for_sync, true)
|
218
218
|
deferrable = EventMachine::DefaultDeferrable.new
|
219
219
|
|
@@ -222,18 +222,17 @@ module Ably::Realtime
|
|
222
222
|
members.map { |key, presence| presence }.tap do |filtered_members|
|
223
223
|
filtered_members.keep_if { |presence| presence.connection_id == options[:connection_id] } if options[:connection_id]
|
224
224
|
filtered_members.keep_if { |presence| presence.client_id == options[:client_id] } if options[:client_id]
|
225
|
+
end.tap do |current_members|
|
226
|
+
yield current_members if block_given?
|
227
|
+
deferrable.succeed current_members
|
225
228
|
end
|
226
229
|
end
|
227
230
|
|
228
231
|
if !wait_for_sync || sync_complete?
|
229
|
-
|
230
|
-
success_block.call result if block_given?
|
231
|
-
deferrable.succeed result
|
232
|
+
result_block.call
|
232
233
|
else
|
233
234
|
sync_pubsub.once(:done) do
|
234
|
-
|
235
|
-
success_block.call result if block_given?
|
236
|
-
deferrable.succeed result
|
235
|
+
result_block.call
|
237
236
|
end
|
238
237
|
|
239
238
|
sync_pubsub.once(:failed) do |error|
|
@@ -486,7 +485,7 @@ module Ably::Realtime
|
|
486
485
|
|
487
486
|
def send_protocol_message_and_transition_state_to(action, options = {}, &success_block)
|
488
487
|
deferrable = options.fetch(:deferrable) { raise ArgumentError, 'option :deferrable is required' }
|
489
|
-
client_id = options.fetch(:client_id)
|
488
|
+
client_id = options.fetch(:client_id) { raise ArgumentError, 'option :client_id is required' }
|
490
489
|
target_state = options.fetch(:target_state, nil)
|
491
490
|
failed_state = options.fetch(:failed_state, nil)
|
492
491
|
|
@@ -509,14 +508,14 @@ module Ably::Realtime
|
|
509
508
|
end
|
510
509
|
end
|
511
510
|
|
512
|
-
def deferrable_succeed(deferrable, *args
|
513
|
-
|
514
|
-
EventMachine.next_tick { deferrable.succeed self, *args } # allow callback to be added to the returned Deferrable
|
511
|
+
def deferrable_succeed(deferrable, *args)
|
512
|
+
yield self, *args if block_given?
|
513
|
+
EventMachine.next_tick { deferrable.succeed self, *args } # allow callback to be added to the returned Deferrable before calling succeed
|
515
514
|
deferrable
|
516
515
|
end
|
517
516
|
|
518
|
-
def deferrable_fail(deferrable, *args
|
519
|
-
|
517
|
+
def deferrable_fail(deferrable, *args)
|
518
|
+
yield self, *args if block_given?
|
520
519
|
EventMachine.next_tick { deferrable.fail self, *args } # allow errback to be added to the returned Deferrable
|
521
520
|
deferrable
|
522
521
|
end
|
data/lib/ably/util/crypto.rb
CHANGED
@@ -62,7 +62,7 @@ module Ably::Util
|
|
62
62
|
# @return [String]
|
63
63
|
#
|
64
64
|
def decrypt(encrypted_payload_with_iv)
|
65
|
-
raise Ably::Exceptions::
|
65
|
+
raise Ably::Exceptions::CipherError, 'iv is missing or not long enough' unless encrypted_payload_with_iv.length >= BLOCK_LENGTH*2
|
66
66
|
|
67
67
|
iv = encrypted_payload_with_iv.slice(0...BLOCK_LENGTH)
|
68
68
|
encrypted_payload = encrypted_payload_with_iv.slice(BLOCK_LENGTH..-1)
|
data/lib/ably/version.rb
CHANGED
@@ -60,8 +60,9 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
context 'with lots of messages published with a single client and channel' do
|
63
|
-
let(:messages_sent)
|
64
|
-
let(:
|
63
|
+
let(:messages_sent) { 30 }
|
64
|
+
let(:rate_per_second) { 4 }
|
65
|
+
let(:limit) { 15 }
|
65
66
|
|
66
67
|
def ensure_message_history_direction_and_paging_is_correct(direction)
|
67
68
|
channel.history(direction: direction, limit: limit) do |history|
|
@@ -102,10 +103,10 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
105
|
-
context 'in multiple ProtocolMessages' do
|
106
|
+
context 'in multiple ProtocolMessages', em_timeout: (30 / 4) + 20 do
|
106
107
|
it 'retrieves limited history forwards with pagination' do
|
107
108
|
messages_sent.times do |index|
|
108
|
-
EventMachine.add_timer(index.to_f /
|
109
|
+
EventMachine.add_timer(index.to_f / rate_per_second) do
|
109
110
|
channel.publish('event', "history#{index}") do
|
110
111
|
next unless index == messages_sent - 1
|
111
112
|
ensure_message_history_direction_and_paging_is_correct :forwards
|
@@ -116,7 +117,7 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
116
117
|
|
117
118
|
it 'retrieves limited history backwards with pagination' do
|
118
119
|
messages_sent.times.to_a.reverse.each do |index|
|
119
|
-
EventMachine.add_timer((messages_sent - index).to_f /
|
120
|
+
EventMachine.add_timer((messages_sent - index).to_f / rate_per_second) do
|
120
121
|
channel.publish('event', "history#{index}") do
|
121
122
|
next unless index == 0
|
122
123
|
ensure_message_history_direction_and_paging_is_correct :backwards if index == 0
|