async 1.14.0 → 1.15.0

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
  SHA256:
3
- metadata.gz: e95eca0cff51fba91c446924485001f6bd9d63978d92a15b583bbb8916b7c53b
4
- data.tar.gz: 463002c552022842360fb031aee28c6286ed7af44761e3e8e55b60c40f1094bb
3
+ metadata.gz: 3722acb6246ee95cecd02b7d763cf695eabe3726510d2eda756ecfe3e809632e
4
+ data.tar.gz: da8e9cd294faf48293c39f7577ef6b807d3e46881fb99f248a7d3369bbc2d182
5
5
  SHA512:
6
- metadata.gz: 8d2848633ef85c07e88321c1cc5f4eb890fc53eb66c973dcf182ab5b535fa211b3493d1a265500c83a359bcd673912ea9b77a076e0c818add4ad82b7d5b35a11
7
- data.tar.gz: 9814c99bbdb06a4993aefd573cf77795d813ee0f129d93cd7df1cc29522cd4f2b11b212a4d9c91d45bdd9f78114ee21ca55dac0fa51438a877124e08e69dd382
6
+ metadata.gz: b69666de33bf4b97a4b72a9b9e6ecce98651dbc7fc6eab8c124946f979731fdb3b349d3143b6763a5cf2a41b2a2725d8186d3d2903603667dbd5ac973aea7686
7
+ data.tar.gz: 3e5a5211537c71bc368aeb7b1d7396693ad6f8908bdbf8e20a5a3baf395a0bb908eddbab2e05f3293667c3e25b2b75d08909df7dc6540d47522f411361ff9628
data/README.md CHANGED
@@ -270,7 +270,7 @@ You can wrap asynchronous operations in a timeout. This ensures that malicious s
270
270
  require 'async'
271
271
 
272
272
  Async do |task|
273
- task.timeout(1) do
273
+ task.with_timeout(1) do
274
274
  task.sleep 100
275
275
  rescue Async::TimeoutError
276
276
  puts "I timed out!"
@@ -13,7 +13,7 @@ class IO
13
13
 
14
14
  monitor = reactor.add_io(fiber, descriptor, state)
15
15
 
16
- fiber.timeout(duration) do
16
+ fiber.with_timeout(duration) do
17
17
  result = Fiber.yield
18
18
  raise result if result.is_a? Exception
19
19
  end
@@ -80,12 +80,12 @@ module Async
80
80
  @subjects[subject.class] = false
81
81
  end
82
82
 
83
- def log(level, *args, &block)
83
+ def log(level, *arguments, &block)
84
84
  unless level.is_a? Symbol
85
85
  level = LEVELS[level]
86
86
  end
87
87
 
88
- self.send(level, *args, &block)
88
+ self.send(level, *arguments, &block)
89
89
  end
90
90
 
91
91
  def format(subject = nil, *arguments, &block)
@@ -204,7 +204,6 @@ module Async
204
204
  @children.each(&:stop)
205
205
 
206
206
  # TODO Should we also clear all timers?
207
-
208
207
  @selector.close
209
208
  @selector = nil
210
209
  end
@@ -231,18 +230,15 @@ module Async
231
230
  timer.cancel if timer
232
231
  end
233
232
 
234
- # Invoke the block, but after the timeout, raise {TimeoutError} in any
235
- # currenly blocking operation.
233
+ # Invoke the block, but after the specified timeout, raise {TimeoutError} in any currenly blocking operation. If the block runs to completion before the timeout occurs or there are no non-blocking operations after the timeout expires, the code will complete without any exception.
236
234
  # @param duration [Numeric] The time in seconds, in which the task should
237
235
  # complete.
238
- def timeout(duration, exception = TimeoutError)
239
- backtrace = caller
236
+ def with_timeout(timeout, exception = TimeoutError)
240
237
  fiber = Fiber.current
241
238
 
242
- timer = self.after(duration) do
239
+ timer = self.after(timeout) do
243
240
  if fiber.alive?
244
241
  error = exception.new("execution expired")
245
- error.set_backtrace backtrace
246
242
  fiber.resume error
247
243
  end
248
244
  end
@@ -251,5 +247,12 @@ module Async
251
247
  ensure
252
248
  timer.cancel if timer
253
249
  end
250
+
251
+ # TODO remove
252
+ def timeout(*args, &block)
253
+ warn "#{self.class}\#timeout(...) is deprecated, use #{self.class}\#with_timeout(...) instead."
254
+
255
+ with_timeout(*args, &block)
256
+ end
254
257
  end
255
258
  end
@@ -76,7 +76,7 @@ module Async
76
76
 
77
77
  # @attr ios [Reactor] The reactor the task was created within.
78
78
  attr :reactor
79
- def_delegators :@reactor, :timeout, :sleep
79
+ def_delegators :@reactor, :with_timeout, :timeout, :sleep
80
80
 
81
81
  # Yield back to the reactor and allow other fibers to execute.
82
82
  def yield
@@ -90,7 +90,7 @@ module Async
90
90
  # @attr status [Symbol] The status of the execution of the fiber, one of `:initialized`, `:running`, `:complete`, `:stopped` or `:failed`.
91
91
  attr :status
92
92
 
93
- # Resume the execution of the task.
93
+ # Begin the execution of the task.
94
94
  def run(*args)
95
95
  if @status == :initialized
96
96
  @status = :running
@@ -124,6 +124,7 @@ module Async
124
124
 
125
125
  # Deprecated.
126
126
  alias result wait
127
+ # Soon to become attr :result
127
128
 
128
129
  # Stop the task and all of its children.
129
130
  # @return [void]
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Async
22
- VERSION = "1.14.0"
22
+ VERSION = "1.15.0"
23
23
  end
@@ -92,14 +92,14 @@ module Async
92
92
  end
93
93
 
94
94
  # Wait for the io to become readable.
95
- def wait_readable(duration = nil)
95
+ def wait_readable(timeout = nil)
96
96
  raise WaitError if @readable
97
97
 
98
98
  self.reactor = Task.current.reactor
99
99
 
100
100
  begin
101
101
  @readable = Fiber.current
102
- wait_for(duration)
102
+ wait_for(timeout)
103
103
  ensure
104
104
  @readable = nil
105
105
  @monitor.interests = interests if @monitor
@@ -107,14 +107,14 @@ module Async
107
107
  end
108
108
 
109
109
  # Wait for the io to become writable.
110
- def wait_writable(duration = nil)
110
+ def wait_writable(timeout = nil)
111
111
  raise WaitError if @writable
112
112
 
113
113
  self.reactor = Task.current.reactor
114
114
 
115
115
  begin
116
116
  @writable = Fiber.current
117
- wait_for(duration)
117
+ wait_for(timeout)
118
118
  ensure
119
119
  @writable = nil
120
120
  @monitor.interests = interests if @monitor
@@ -123,14 +123,14 @@ module Async
123
123
 
124
124
  # Wait fo the io to become either readable or writable.
125
125
  # @param duration [Float] timeout after the given duration if not `nil`.
126
- def wait_any(duration = nil)
126
+ def wait_any(timeout = nil)
127
127
  raise WaitError if @any
128
128
 
129
129
  self.reactor = Task.current.reactor
130
130
 
131
131
  begin
132
132
  @any = Fiber.current
133
- wait_for(duration)
133
+ wait_for(timeout)
134
134
  ensure
135
135
  @any = nil
136
136
  @monitor.interests = interests if @monitor
@@ -195,7 +195,7 @@ module Async
195
195
  end
196
196
  end
197
197
 
198
- def wait_for(duration)
198
+ def wait_for(timeout)
199
199
  if @monitor
200
200
  @monitor.interests = interests
201
201
  else
@@ -203,8 +203,8 @@ module Async
203
203
  end
204
204
 
205
205
  # If the user requested an explicit timeout for this operation:
206
- if duration
207
- @reactor.timeout(duration) do
206
+ if timeout
207
+ @reactor.with_timeout(timeout) do
208
208
  Task.yield
209
209
  end
210
210
  else
@@ -18,6 +18,8 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
+ require 'benchmark/ips'
22
+
21
23
  RSpec.describe Async::Reactor do
22
24
  describe '#run' do
23
25
  it "can run tasks on different fibers" do
@@ -118,7 +120,7 @@ RSpec.describe Async::Reactor do
118
120
  end
119
121
  end
120
122
 
121
- describe '#timeout' do
123
+ describe '#with_timeout' do
122
124
  let(:duration) {1}
123
125
 
124
126
  it "stops immediately" do
@@ -127,7 +129,7 @@ RSpec.describe Async::Reactor do
127
129
  described_class.run do |task|
128
130
  condition = Async::Condition.new
129
131
 
130
- task.timeout(duration) do
132
+ task.with_timeout(duration) do
131
133
  task.async do
132
134
  condition.wait
133
135
  end
@@ -150,12 +152,29 @@ RSpec.describe Async::Reactor do
150
152
  it "raises specified exception" do
151
153
  expect do
152
154
  described_class.run do |task|
153
- task.timeout(0.0, timeout_class) do
155
+ task.with_timeout(0.0, timeout_class) do
154
156
  task.sleep(1.0)
155
157
  end
156
158
  end.wait
157
159
  end.to raise_exception(timeout_class)
158
160
  end
161
+
162
+ it "should be fast to use timeouts" do
163
+ Benchmark.ips do |x|
164
+ x.report('Reactor#with_timeout') do |repeats|
165
+ Async do |task|
166
+ reactor = task.reactor
167
+
168
+ repeats.times do
169
+ reactor.with_timeout(1) do
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ x.compare!
176
+ end
177
+ end
159
178
  end
160
179
 
161
180
  describe '#to_s' do
@@ -199,10 +199,10 @@ RSpec.describe Async::Task do
199
199
  end
200
200
  end
201
201
 
202
- describe '#timeout' do
202
+ describe '#with_timeout' do
203
203
  it "can extend timeout" do
204
204
  reactor.async do |task|
205
- task.timeout(0.2) do |timer|
205
+ task.with_timeout(0.2) do |timer|
206
206
  task.sleep(0.1)
207
207
 
208
208
  expect(timer.fires_in).to be_within(10).percent_of(0.1)
@@ -221,7 +221,7 @@ RSpec.describe Async::Task do
221
221
 
222
222
  reactor.async do |task|
223
223
  begin
224
- task.timeout(0.01) do
224
+ task.with_timeout(0.01) do
225
225
  state = :started
226
226
  task.sleep(10)
227
227
  state = :finished
@@ -241,7 +241,7 @@ RSpec.describe Async::Task do
241
241
 
242
242
  reactor.async do |task|
243
243
  state = :started
244
- task.timeout(0.01) do
244
+ task.with_timeout(0.01) do
245
245
  task.sleep(0.001)
246
246
  state = :finished
247
247
  end
@@ -251,6 +251,26 @@ RSpec.describe Async::Task do
251
251
 
252
252
  expect(state).to be == :finished
253
253
  end
254
+
255
+ def sleep_forever
256
+ while true
257
+ Async::Task.current.sleep(1)
258
+ end
259
+ end
260
+
261
+ it "contains useful backtrace" do
262
+ task = Async do |task|
263
+ task.with_timeout(1.0) do
264
+ sleep_forever
265
+ end
266
+ end
267
+
268
+ expect{task.wait}.to raise_error(Async::TimeoutError)
269
+
270
+ # TODO replace this with task.result
271
+ task.wait rescue error = $!
272
+ expect(error.backtrace).to include(/sleep_forever/)
273
+ end
254
274
  end
255
275
 
256
276
  describe '#wait' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-17 00:00:00.000000000 Z
11
+ date: 2019-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r