ably 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|