ably-rest 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ably-rest.gemspec +4 -1
- data/lib/submodules/ably-ruby/ably.gemspec +3 -4
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base.rb +2 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +30 -15
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +5 -0
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +29 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +16 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +109 -51
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 610101b34de5bd5283cda560a5aff2d115842529
|
4
|
+
data.tar.gz: 499b0a8ec74ab12356b7e8e94330f13283670458
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 650f6502ebfd7dd5f3183cb1bb42f98be067145859a4e3d39a692e1abb38c3dbf18cd0b363a6d21a586321c04288900c63b914625e5a082436e9f8c8220c1bdd
|
7
|
+
data.tar.gz: f5926a4f1d213782974e1c5cd79ac4cb12c6dac941eafb7d8de2a6f49cc6c9e25b4e028de177d6da4ee40ba230d1d0062b8bda289b39d437f9015600c9c56d54
|
data/ably-rest.gemspec
CHANGED
@@ -48,7 +48,10 @@ Gem::Specification.new do |spec|
|
|
48
48
|
spec.add_development_dependency 'yard', '~> 0.9'
|
49
49
|
spec.add_development_dependency 'webmock', '~> 2.0'
|
50
50
|
|
51
|
-
|
51
|
+
if RUBY_VERSION.match(/^1/)
|
52
|
+
spec.add_development_dependency 'public_suffix', '~> 1.4.6' # Later versions do not support Ruby 1.9
|
53
|
+
else
|
54
|
+
spec.add_development_dependency 'coveralls'
|
52
55
|
spec.add_development_dependency 'pry'
|
53
56
|
spec.add_development_dependency 'pry-byebug'
|
54
57
|
end
|
@@ -40,11 +40,10 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency 'yard', '~> 0.9'
|
41
41
|
spec.add_development_dependency 'webmock', '~> 2.0'
|
42
42
|
|
43
|
-
|
43
|
+
if RUBY_VERSION.match(/^1/)
|
44
|
+
spec.add_development_dependency 'public_suffix', '~> 1.4.6' # Later versions do not support Ruby 1.9
|
45
|
+
else
|
44
46
|
spec.add_development_dependency 'coveralls'
|
45
|
-
end
|
46
|
-
|
47
|
-
unless RUBY_VERSION.match(/^1/)
|
48
47
|
spec.add_development_dependency 'pry'
|
49
48
|
spec.add_development_dependency 'pry-byebug'
|
50
49
|
end
|
@@ -96,7 +96,8 @@ module Ably::Models::MessageEncoders
|
|
96
96
|
end
|
97
97
|
|
98
98
|
# @api private
|
99
|
-
def self.register_default_encoders(client,
|
99
|
+
def self.register_default_encoders(client, options = {})
|
100
|
+
binary_protocol = !!options[:binary_protocol]
|
100
101
|
client.register_encoder Ably::Models::MessageEncoders::Utf8
|
101
102
|
client.register_encoder Ably::Models::MessageEncoders::Json
|
102
103
|
client.register_encoder Ably::Models::MessageEncoders::Cipher
|
@@ -50,18 +50,14 @@ module Ably
|
|
50
50
|
#
|
51
51
|
# @return [void]
|
52
52
|
def on(*event_names, &block)
|
53
|
-
event_names
|
54
|
-
callbacks[callbacks_event_coerced(event_name)] << proc_for_block(block)
|
55
|
-
end
|
53
|
+
add_callback event_names, proc_for_block(block)
|
56
54
|
end
|
57
55
|
|
58
56
|
# Equivalent of {#on} but any exception raised in a block will bubble up and cause this client library to fail.
|
59
57
|
# This method should only be used internally by the client library.
|
60
58
|
# @api private
|
61
59
|
def unsafe_on(*event_names, &block)
|
62
|
-
event_names
|
63
|
-
callbacks[callbacks_event_coerced(event_name)] << proc_for_block(block, unsafe: true)
|
64
|
-
end
|
60
|
+
add_callback event_names, proc_for_block(block, unsafe: true)
|
65
61
|
end
|
66
62
|
|
67
63
|
# On receiving an event maching the event_name, call the provided block only once and remove the registered callback
|
@@ -70,24 +66,20 @@ module Ably
|
|
70
66
|
#
|
71
67
|
# @return [void]
|
72
68
|
def once(*event_names, &block)
|
73
|
-
event_names
|
74
|
-
callbacks[callbacks_event_coerced(event_name)] << proc_for_block(block, delete_once_run: true)
|
75
|
-
end
|
69
|
+
add_callback event_names, proc_for_block(block, delete_once_run: true)
|
76
70
|
end
|
77
71
|
|
78
72
|
# Equivalent of {#once} but any exception raised in a block will bubble up and cause this client library to fail.
|
79
73
|
# This method should only be used internally by the client library.
|
80
74
|
# @api private
|
81
75
|
def unsafe_once(*event_names, &block)
|
82
|
-
event_names
|
83
|
-
callbacks[callbacks_event_coerced(event_name)] << proc_for_block(block, delete_once_run: true, unsafe: true)
|
84
|
-
end
|
76
|
+
add_callback event_names, proc_for_block(block, delete_once_run: true, unsafe: true)
|
85
77
|
end
|
86
78
|
|
87
79
|
# Emit an event with event_name that will in turn call all matching callbacks setup with `on`
|
88
80
|
def emit(event_name, *args)
|
89
|
-
callbacks[callbacks_event_coerced(event_name)].
|
90
|
-
clone.
|
81
|
+
[callbacks_any, callbacks[callbacks_event_coerced(event_name)]].each do |callback_arr|
|
82
|
+
callback_arr.clone.
|
91
83
|
select do |proc_hash|
|
92
84
|
if proc_hash[:unsafe]
|
93
85
|
proc_hash[:emit_proc].call(*args)
|
@@ -95,8 +87,9 @@ module Ably
|
|
95
87
|
safe_yield proc_hash[:emit_proc], *args
|
96
88
|
end
|
97
89
|
end.each do |callback|
|
98
|
-
|
90
|
+
callback_arr.delete callback
|
99
91
|
end
|
92
|
+
end
|
100
93
|
end
|
101
94
|
|
102
95
|
# Remove all callbacks for event_name.
|
@@ -121,6 +114,14 @@ module Ably
|
|
121
114
|
callbacks[callbacks_event_coerced(event_name)].clear
|
122
115
|
end
|
123
116
|
end
|
117
|
+
|
118
|
+
if event_names.empty?
|
119
|
+
if block_given?
|
120
|
+
callbacks_any.delete_if { |proc_hash| proc_hash[:block] == block }
|
121
|
+
else
|
122
|
+
callbacks_any.clear
|
123
|
+
end
|
124
|
+
end
|
124
125
|
end
|
125
126
|
|
126
127
|
private
|
@@ -128,6 +129,16 @@ module Ably
|
|
128
129
|
klass.extend ClassMethods
|
129
130
|
end
|
130
131
|
|
132
|
+
def add_callback(event_names, proc_block)
|
133
|
+
if event_names.empty?
|
134
|
+
callbacks_any << proc_block
|
135
|
+
else
|
136
|
+
event_names.each do |event_name|
|
137
|
+
callbacks[callbacks_event_coerced(event_name)] << proc_block
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
131
142
|
# Create a Hash with a proc that calls the provided block and returns true if option :delete_once_run is set to true.
|
132
143
|
# #emit automatically deletes any blocks that return true thus allowing a block to be run once
|
133
144
|
def proc_for_block(block, options = {})
|
@@ -145,6 +156,10 @@ module Ably
|
|
145
156
|
@callbacks ||= Hash.new { |hash, key| hash[key] = [] }
|
146
157
|
end
|
147
158
|
|
159
|
+
def callbacks_any
|
160
|
+
@callbacks_any ||= []
|
161
|
+
end
|
162
|
+
|
148
163
|
def callbacks_event_coerced(event_name)
|
149
164
|
if self.class.event_emitter_coerce_proc
|
150
165
|
self.class.event_emitter_coerce_proc.call(event_name)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module Ably
|
2
4
|
module Realtime
|
3
5
|
# Client for the Ably Realtime API
|
@@ -68,6 +70,9 @@ module Ably
|
|
68
70
|
#
|
69
71
|
# @param (see Ably::Rest::Client#initialize)
|
70
72
|
# @option options (see Ably::Rest::Client#initialize)
|
73
|
+
# @option options [Proc] :auth_callback when provided, the Proc will be called with the token params hash as the first argument, whenever a new token is required.
|
74
|
+
# Whilst the proc is called synchronously, it does not block the EventMachine reactor as it is run in a separate thread.
|
75
|
+
# The Proc should return a token string, {Ably::Models::TokenDetails} or JSON equivalent, {Ably::Models::TokenRequest} or JSON equivalent
|
71
76
|
# @option options [Boolean] :queue_messages If false, this disables the default behaviour whereby the library queues messages on a connection in the disconnected or connecting states
|
72
77
|
# @option options [Boolean] :echo_messages If false, prevents messages originating from this connection being echoed back on the same connection
|
73
78
|
# @option options [String] :recover When a recover option is specified a connection inherits the state of a previous connection that may have existed under a different instance of the Realtime library, please refer to the API documentation for further information on connection state recovery
|
@@ -3,12 +3,12 @@ require 'ably/rest/channels'
|
|
3
3
|
require 'ably/rest/client'
|
4
4
|
require 'ably/rest/presence'
|
5
5
|
|
6
|
+
require 'ably/models/message_encoders/base'
|
7
|
+
|
6
8
|
Dir.glob(File.expand_path("models/*.rb", File.dirname(__FILE__))).each do |file|
|
7
9
|
require file
|
8
10
|
end
|
9
11
|
|
10
|
-
require 'ably/models/message_encoders/base'
|
11
|
-
|
12
12
|
module Ably
|
13
13
|
# Rest provides the top-level class to be instanced for the Ably Rest library
|
14
14
|
#
|
@@ -186,6 +186,35 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
|
+
context 'with auth_callback blocking' do
|
190
|
+
let(:rest_auth_client) { Ably::Rest::Client.new(default_options.merge(key: api_key)) }
|
191
|
+
let(:client_options) { default_options.merge(auth_callback: auth_callback) }
|
192
|
+
let(:pause) { 5 }
|
193
|
+
|
194
|
+
context 'with a slow auth callback response' do
|
195
|
+
let(:auth_callback) do
|
196
|
+
Proc.new do
|
197
|
+
sleep pause
|
198
|
+
rest_auth_client.auth.request_token
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'asynchronously authenticates' do
|
203
|
+
timers_called = 0
|
204
|
+
block = Proc.new do
|
205
|
+
timers_called += 1
|
206
|
+
EventMachine.add_timer(0.5, &block)
|
207
|
+
end
|
208
|
+
block.call
|
209
|
+
client.connect
|
210
|
+
client.connection.on(:connected) do
|
211
|
+
expect(timers_called).to be >= (pause-1) / 0.5
|
212
|
+
stop_reactor
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
189
218
|
context 'when implicitly called, with an explicit ClientOptions client_id' do
|
190
219
|
let(:client_id) { random_str }
|
191
220
|
let(:client_options) { default_options.merge(auth_callback: Proc.new { auth_token_object }, client_id: client_id, log_level: :none) }
|
@@ -1278,6 +1278,22 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1278
1278
|
end
|
1279
1279
|
|
1280
1280
|
context 'connection state change' do
|
1281
|
+
# See https://github.com/ably/ably-ruby/issues/103
|
1282
|
+
it 'emits event to all and single subscribers' do
|
1283
|
+
connected_emitted = []
|
1284
|
+
block = Proc.new do |state_change|
|
1285
|
+
if state_change.current == :connected
|
1286
|
+
connected_emitted << state_change
|
1287
|
+
EventMachine.add_timer(0.5) do
|
1288
|
+
expect(connected_emitted.length).to eql(2)
|
1289
|
+
stop_reactor
|
1290
|
+
end
|
1291
|
+
end
|
1292
|
+
end
|
1293
|
+
connection.on(&block)
|
1294
|
+
connection.on(:connected, &block)
|
1295
|
+
end
|
1296
|
+
|
1281
1297
|
it 'emits a ConnectionStateChange object' do
|
1282
1298
|
connection.on(:connected) do |connection_state_change|
|
1283
1299
|
expect(connection_state_change).to be_a(Ably::Models::ConnectionStateChange)
|
@@ -128,17 +128,34 @@ describe Ably::Modules::EventEmitter do
|
|
128
128
|
end
|
129
129
|
|
130
130
|
context '#on' do
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
131
|
+
context 'with event specified' do
|
132
|
+
it 'calls the block every time an event is emitted only' do
|
133
|
+
block_called = 0
|
134
|
+
subject.on('event') { block_called += 1 }
|
135
|
+
3.times { subject.emit 'event', 'data' }
|
136
|
+
expect(block_called).to eql(3)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'catches exceptions in the provided block, logs the error and continues' do
|
140
|
+
expect(subject.logger).to receive(:error).with(/Intentional exception/)
|
141
|
+
subject.on(:event) { raise 'Intentional exception' }
|
142
|
+
subject.emit :event
|
143
|
+
end
|
136
144
|
end
|
137
145
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
146
|
+
context 'with no event specified' do
|
147
|
+
it 'calls the block every time an event is emitted only' do
|
148
|
+
block_called = 0
|
149
|
+
subject.on { block_called += 1 }
|
150
|
+
3.times { subject.emit 'event', 'data' }
|
151
|
+
expect(block_called).to eql(3)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'catches exceptions in the provided block, logs the error and continues' do
|
155
|
+
expect(subject.logger).to receive(:error).with(/Intentional exception/)
|
156
|
+
subject.on { raise 'Intentional exception' }
|
157
|
+
subject.emit :event
|
158
|
+
end
|
142
159
|
end
|
143
160
|
end
|
144
161
|
|
@@ -157,25 +174,50 @@ describe Ably::Modules::EventEmitter do
|
|
157
174
|
end
|
158
175
|
|
159
176
|
context '#once' do
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
177
|
+
context 'with event specified' do
|
178
|
+
it 'calls the block the first time an event is emitted only' do
|
179
|
+
block_called = 0
|
180
|
+
subject.once('event') { block_called += 1 }
|
181
|
+
3.times { subject.emit 'event', 'data' }
|
182
|
+
expect(block_called).to eql(1)
|
183
|
+
end
|
166
184
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
185
|
+
it 'does not remove other blocks after it is called' do
|
186
|
+
block_called = 0
|
187
|
+
subject.once('event') { block_called += 1 }
|
188
|
+
subject.on('event') { block_called += 1 }
|
189
|
+
3.times { subject.emit 'event', 'data' }
|
190
|
+
expect(block_called).to eql(4)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'catches exceptions in the provided block, logs the error and continues' do
|
194
|
+
expect(subject.logger).to receive(:error).with(/Intentional exception/)
|
195
|
+
subject.once(:event) { raise 'Intentional exception' }
|
196
|
+
subject.emit :event
|
197
|
+
end
|
173
198
|
end
|
174
199
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
200
|
+
context 'with no event specified' do
|
201
|
+
it 'calls the block the first time an event is emitted only' do
|
202
|
+
block_called = 0
|
203
|
+
subject.once { block_called += 1 }
|
204
|
+
3.times { subject.emit 'event', 'data' }
|
205
|
+
expect(block_called).to eql(1)
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'does not remove other blocks after it is called' do
|
209
|
+
block_called = 0
|
210
|
+
subject.once { block_called += 1 }
|
211
|
+
subject.on { block_called += 1 }
|
212
|
+
3.times { subject.emit 'event', 'data' }
|
213
|
+
expect(block_called).to eql(4)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'catches exceptions in the provided block, logs the error and continues' do
|
217
|
+
expect(subject.logger).to receive(:error).with(/Intentional exception/)
|
218
|
+
subject.once { raise 'Intentional exception' }
|
219
|
+
subject.emit :event
|
220
|
+
end
|
179
221
|
end
|
180
222
|
end
|
181
223
|
|
@@ -196,41 +238,57 @@ describe Ably::Modules::EventEmitter do
|
|
196
238
|
context '#off' do
|
197
239
|
let(:callback) { Proc.new { |msg| obj.received_message msg } }
|
198
240
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
after do
|
204
|
-
subject.emit :message, msg
|
205
|
-
end
|
241
|
+
context 'with event specified in on handler' do
|
242
|
+
before do
|
243
|
+
subject.on(:message, &callback)
|
244
|
+
end
|
206
245
|
|
207
|
-
|
208
|
-
|
209
|
-
expect(obj).to_not receive(:received_message).with(msg)
|
210
|
-
subject.off(:message, &callback)
|
246
|
+
after do
|
247
|
+
subject.emit :message, msg
|
211
248
|
end
|
212
249
|
|
213
|
-
|
214
|
-
|
215
|
-
|
250
|
+
context 'with event names as arguments' do
|
251
|
+
it 'deletes matching callbacks' do
|
252
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
253
|
+
subject.off(:message, &callback)
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'deletes all callbacks if not block given' do
|
257
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
258
|
+
subject.off(:message)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'continues if the block does not exist' do
|
262
|
+
expect(obj).to receive(:received_message).with(msg)
|
263
|
+
subject.off(:message) { true }
|
264
|
+
end
|
216
265
|
end
|
217
266
|
|
218
|
-
|
219
|
-
|
220
|
-
|
267
|
+
context 'without any event names' do
|
268
|
+
it 'deletes all matching callbacks' do
|
269
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
270
|
+
subject.off(&callback)
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'deletes all callbacks if not block given' do
|
274
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
275
|
+
subject.off
|
276
|
+
end
|
221
277
|
end
|
222
278
|
end
|
223
279
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
280
|
+
it 'removes handler added with no event specified' do
|
281
|
+
subject.on(&callback)
|
282
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
283
|
+
subject.off(&callback)
|
284
|
+
subject.emit :message, msg
|
285
|
+
end
|
229
286
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
287
|
+
it 'leaves handler when event specified' do
|
288
|
+
subject.on(&callback)
|
289
|
+
expect(obj).to receive(:received_message).with(msg)
|
290
|
+
subject.off(:foo, &callback)
|
291
|
+
subject.emit :message, msg
|
234
292
|
end
|
235
293
|
end
|
236
294
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ably-rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew O'Riordan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '2.0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: coveralls
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: pry
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|