ably-rest 0.9.2 → 0.9.3
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/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
|