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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 006c13b2408ff07c78159727a7e0bbd1a2eea9ab
4
- data.tar.gz: 691848a554d61eb6c785cc7515f169e36bed8241
3
+ metadata.gz: 610101b34de5bd5283cda560a5aff2d115842529
4
+ data.tar.gz: 499b0a8ec74ab12356b7e8e94330f13283670458
5
5
  SHA512:
6
- metadata.gz: 5ef3a684409bf54433d1c81b76da2555e6aa885dc547e4c11c8e4e94f24adf25c56cc84a2613f5d8b11c03294126a5b03b826a6a744820e1765b7eb4433eebf5
7
- data.tar.gz: 562e4212388a59f3b53e699ff1933a1d02563b3c62af75370919c8dba10b984013e43a38bc73a33b364fe65952537d02d96eb77b30953e2c1df9d81382caf7fa
6
+ metadata.gz: 650f6502ebfd7dd5f3183cb1bb42f98be067145859a4e3d39a692e1abb38c3dbf18cd0b363a6d21a586321c04288900c63b914625e5a082436e9f8c8220c1bdd
7
+ data.tar.gz: f5926a4f1d213782974e1c5cd79ac4cb12c6dac941eafb7d8de2a6f49cc6c9e25b4e028de177d6da4ee40ba230d1d0062b8bda289b39d437f9015600c9c56d54
@@ -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
- unless RUBY_VERSION.match(/^1/)
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
- unless RUBY_VERSION.match(/^1/)
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, binary_protocol: false)
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.each do |event_name|
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.each do |event_name|
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.each do |event_name|
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.each do |event_name|
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
- callbacks[callbacks_event_coerced(event_name)].delete callback
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
  #
@@ -1,6 +1,7 @@
1
1
  require 'faraday'
2
2
  require 'json'
3
3
  require 'logger'
4
+ require 'uri'
4
5
 
5
6
  require 'ably/rest/middleware/exceptions'
6
7
 
@@ -1,5 +1,5 @@
1
1
  module Ably
2
- VERSION = '0.9.2'
2
+ VERSION = '0.9.3'
3
3
  PROTOCOL_VERSION = '0.9'
4
4
 
5
5
  # Allow a variant to be configured for all instances of this client library
@@ -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
- it 'calls the block every time an event is emitted only' do
132
- block_called = 0
133
- subject.on('event') { block_called += 1 }
134
- 3.times { subject.emit 'event', 'data' }
135
- expect(block_called).to eql(3)
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
- it 'catches exceptions in the provided block, logs the error and continues' do
139
- expect(subject.logger).to receive(:error).with(/Intentional exception/)
140
- subject.on(:event) { raise 'Intentional exception' }
141
- subject.emit :event
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
- it 'calls the block the first time an event is emitted only' do
161
- block_called = 0
162
- subject.once('event') { block_called += 1 }
163
- 3.times { subject.emit 'event', 'data' }
164
- expect(block_called).to eql(1)
165
- end
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
- it 'does not remove other blocks after it is called' do
168
- block_called = 0
169
- subject.once('event') { block_called += 1 }
170
- subject.on('event') { block_called += 1 }
171
- 3.times { subject.emit 'event', 'data' }
172
- expect(block_called).to eql(4)
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
- it 'catches exceptions in the provided block, logs the error and continues' do
176
- expect(subject.logger).to receive(:error).with(/Intentional exception/)
177
- subject.once(:event) { raise 'Intentional exception' }
178
- subject.emit :event
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
- before do
200
- subject.on(:message, &callback)
201
- end
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
- context 'with event names as arguments' do
208
- it 'deletes matching callbacks' do
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
- it 'deletes all callbacks if not block given' do
214
- expect(obj).to_not receive(:received_message).with(msg)
215
- subject.off(:message)
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
- it 'continues if the block does not exist' do
219
- expect(obj).to receive(:received_message).with(msg)
220
- subject.off(:message) { true }
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
- context 'without any event names' do
225
- it 'deletes all matching callbacks' do
226
- expect(obj).to_not receive(:received_message).with(msg)
227
- subject.off(&callback)
228
- end
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
- it 'deletes all callbacks if not block given' do
231
- expect(obj).to_not receive(:received_message).with(msg)
232
- subject.off
233
- end
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.2
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-17 00:00:00.000000000 Z
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