async 1.12.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,9 +26,9 @@ RSpec.describe Async::Reactor do
26
26
  outer_reactor = Async::Task.current.reactor
27
27
  inner_reactor = nil
28
28
 
29
- task = described_class.run do |task|
29
+ described_class.run do |task|
30
30
  inner_reactor = task.reactor
31
- end
31
+ end
32
32
 
33
33
  expect(outer_reactor).to be_kind_of(described_class)
34
34
  expect(outer_reactor).to be_eql(inner_reactor)
@@ -40,9 +40,9 @@ RSpec.describe Async::Reactor do
40
40
  expect(Async::Task.current?).to be_nil
41
41
  inner_reactor = nil
42
42
 
43
- task = described_class.run do |task|
43
+ described_class.run do |task|
44
44
  inner_reactor = task.reactor
45
- end
45
+ end
46
46
 
47
47
  expect(inner_reactor).to be_kind_of(described_class)
48
48
  end
@@ -75,26 +75,26 @@ RSpec.describe Async::Reactor do
75
75
  end
76
76
  it "can't return" do
77
77
  expect do
78
- Async::Reactor.run do |task|
78
+ Async do |task|
79
79
  return
80
- end
81
- end.to raise_error(LocalJumpError)
80
+ end.wait
81
+ end.to raise_exception(LocalJumpError)
82
82
  end
83
83
 
84
84
  it "is closed after running" do
85
85
  reactor = nil
86
86
 
87
- Async::Reactor.run do |task|
87
+ Async do |task|
88
88
  reactor = task.reactor
89
89
  end
90
90
 
91
91
  expect(reactor).to be_closed
92
92
 
93
- expect{reactor.run}.to raise_error(RuntimeError, /closed/)
93
+ expect{reactor.run}.to raise_exception(RuntimeError, /closed/)
94
94
  end
95
95
 
96
96
  it "should return a task" do
97
- result = Async::Reactor.run do |task|
97
+ result = Async do |task|
98
98
  end
99
99
 
100
100
  expect(result).to be_kind_of(Async::Task)
@@ -153,8 +153,8 @@ RSpec.describe Async::Reactor do
153
153
  task.timeout(0.0, timeout_class) do
154
154
  task.sleep(1.0)
155
155
  end
156
- end
157
- end.to raise_error(timeout_class)
156
+ end.wait
157
+ end.to raise_exception(timeout_class)
158
158
  end
159
159
  end
160
160
 
@@ -28,7 +28,7 @@ RSpec.describe Async::Task do
28
28
  task = reactor.async do |task|
29
29
  end
30
30
 
31
- expect{task.run}.to raise_error(RuntimeError, /already running/)
31
+ expect{task.run}.to raise_exception(RuntimeError, /already running/)
32
32
  end
33
33
  end
34
34
 
@@ -54,13 +54,61 @@ RSpec.describe Async::Task do
54
54
  end.wait
55
55
  end.wait
56
56
  end
57
+
58
+ it "can raise exceptions" do
59
+ expect do
60
+ reactor.async do |task|
61
+ raise "boom"
62
+ end.wait
63
+ end.to raise_exception RuntimeError, /boom/
64
+ end
65
+
66
+ it "can raise exception after asynchronous operation" do
67
+ task = nil
68
+
69
+ expect do
70
+ task = reactor.async do |task|
71
+ task.sleep 0.1
72
+
73
+ raise "boom"
74
+ end
75
+ end.to_not raise_exception
76
+
77
+ reactor.run do
78
+ expect do
79
+ task.wait
80
+ end.to raise_exception RuntimeError, /boom/
81
+ end
82
+ end
83
+
84
+ it "can consume exceptions" do
85
+ task = nil
86
+
87
+ expect do
88
+ task = reactor.async(propagate_exceptions: false) do |task|
89
+ raise "boom"
90
+ end
91
+ end.to_not raise_exception
92
+
93
+ expect do
94
+ task.wait
95
+ end.to raise_exception RuntimeError, /boom/
96
+ end
97
+
98
+ it "won't consume non-StandardError exceptions" do
99
+ expect do
100
+ reactor.async(propagate_exceptions: false) do |task|
101
+ raise SignalException.new(:TERM)
102
+ end
103
+ end.to raise_exception(SignalException, /TERM/)
104
+ end
57
105
  end
58
106
 
59
107
  describe '#yield' do
60
108
  it "can yield back to reactor" do
61
109
  state = nil
62
110
 
63
- task = reactor.async do |task|
111
+ reactor.async do |task|
64
112
  state = :started
65
113
  task.yield
66
114
  state = :finished
@@ -90,7 +138,7 @@ RSpec.describe Async::Task do
90
138
  it "should kill direct child" do
91
139
  parent_task = child_task = nil
92
140
 
93
- task = reactor.async do |task|
141
+ reactor.async do |task|
94
142
  parent_task = task
95
143
  reactor.async do |task|
96
144
  child_task = task
@@ -135,7 +183,7 @@ RSpec.describe Async::Task do
135
183
  it "can sleep for the requested duration" do
136
184
  state = nil
137
185
 
138
- task = reactor.async do |task|
186
+ reactor.async do |task|
139
187
  task.sleep(duration)
140
188
  state = :finished
141
189
  end
@@ -152,10 +200,26 @@ RSpec.describe Async::Task do
152
200
  end
153
201
 
154
202
  describe '#timeout' do
203
+ it "can extend timeout" do
204
+ reactor.async do |task|
205
+ task.timeout(0.2) do |timer|
206
+ task.sleep(0.1)
207
+
208
+ expect(timer.fires_in).to be_within(10).percent_of(0.1)
209
+
210
+ timer.reset
211
+
212
+ expect(timer.fires_in).to be_within(10).percent_of(0.2)
213
+ end
214
+ end
215
+
216
+ reactor.run
217
+ end
218
+
155
219
  it "will timeout if execution takes too long" do
156
220
  state = nil
157
221
 
158
- task = reactor.async do |task|
222
+ reactor.async do |task|
159
223
  begin
160
224
  task.timeout(0.01) do
161
225
  state = :started
@@ -175,7 +239,7 @@ RSpec.describe Async::Task do
175
239
  it "won't timeout if execution completes in time" do
176
240
  state = nil
177
241
 
178
- task = reactor.async do |task|
242
+ reactor.async do |task|
179
243
  state = :started
180
244
  task.timeout(0.01) do
181
245
  task.sleep(0.001)
@@ -191,8 +255,6 @@ RSpec.describe Async::Task do
191
255
 
192
256
  describe '#wait' do
193
257
  it "will wait on another task to complete" do
194
- result = nil
195
-
196
258
  apples_task = reactor.async do |task|
197
259
  task.sleep(0.1)
198
260
 
@@ -205,33 +267,43 @@ RSpec.describe Async::Task do
205
267
  :oranges
206
268
  end
207
269
 
208
- fruit_salad_task = reactor.async do |task|
209
- result = [apples_task.result, oranges_task.result]
270
+ fruit_salad = reactor.async do |task|
271
+ [apples_task.wait, oranges_task.wait]
210
272
  end
211
273
 
212
274
  reactor.run
213
275
 
214
- expect(result).to be == [:apples, :oranges]
276
+ expect(fruit_salad.wait).to be == [:apples, :oranges]
277
+ end
278
+
279
+ it "will raise exceptions when checking result" do
280
+ error_task = nil
281
+
282
+ error_task = reactor.async(propagate_exceptions: false) do |task|
283
+ raise RuntimeError, "brain not provided"
284
+ end
285
+
286
+ expect do
287
+ error_task.wait
288
+ end.to raise_exception(RuntimeError, /brain/)
215
289
  end
216
290
 
217
- it "will propagate exceptions" do
291
+ it "will propagate exceptions after async operation" do
218
292
  error_task = nil
219
293
 
220
- error_task = reactor.async do |task|
294
+ error_task = reactor.async(propagate_exceptions: false) do |task|
221
295
  task.sleep(0.1)
222
296
 
223
- raise ArgumentError.new("It simply wasn't good enough")
297
+ raise "boom"
224
298
  end
225
299
 
226
300
  innocent_task = reactor.async do |task|
227
- expect{error_task.result}.to raise_error(ArgumentError, /wasn't good enough/)
301
+ expect{error_task.wait}.to raise_exception RuntimeError, /boom/
228
302
  end
229
303
 
230
- begin
304
+ expect do
231
305
  reactor.run
232
- rescue Exception
233
- retry
234
- end
306
+ end.to_not raise_exception
235
307
 
236
308
  expect(error_task).to be_finished
237
309
  expect(innocent_task).to be_finished
@@ -46,7 +46,9 @@ RSpec.describe Async::Wrapper do
46
46
  end
47
47
 
48
48
  it "can timeout if no event occurs" do
49
- expect(output.wait_readable(0.1)).to be_falsey
49
+ expect do
50
+ output.wait_readable(0.1)
51
+ end.to raise_exception(Async::TimeoutError)
50
52
  end
51
53
 
52
54
  it "can wait for readability in sequential tasks" do
@@ -66,7 +68,7 @@ RSpec.describe Async::Wrapper do
66
68
  reactor.async do
67
69
  expect do
68
70
  output.wait_readable
69
- end.to raise_error(Async::Wrapper::Cancelled)
71
+ end.to raise_exception(Async::Wrapper::Cancelled)
70
72
  end
71
73
 
72
74
  expect(output.monitor).to_not be_nil
@@ -82,7 +84,7 @@ RSpec.describe Async::Wrapper do
82
84
  reactor.async do
83
85
  expect do
84
86
  input.wait_readable
85
- end.to raise_error(Async::Wrapper::Cancelled)
87
+ end.to raise_exception(Async::Wrapper::Cancelled)
86
88
  end
87
89
 
88
90
  # This reproduces the race condition that can occur if two tasks are resumed in sequence.
@@ -93,14 +95,14 @@ RSpec.describe Async::Wrapper do
93
95
  # Resume task 2:
94
96
  expect do
95
97
  output.resume
96
- end.to_not raise_error
98
+ end.to_not raise_exception
97
99
  end
98
100
 
99
101
  it "can be cancelled" do
100
102
  reactor.async do
101
103
  expect do
102
104
  input.wait_readable
103
- end.to raise_error(Async::Wrapper::Cancelled)
105
+ end.to raise_exception(Async::Wrapper::Cancelled)
104
106
  end
105
107
 
106
108
  expect(input.monitor).to_not be_nil
@@ -121,7 +123,7 @@ RSpec.describe Async::Wrapper do
121
123
  reactor.async do
122
124
  expect do
123
125
  input.wait_readable(1)
124
- end.to raise_error(Async::Wrapper::Cancelled)
126
+ end.to raise_exception(Async::Wrapper::Cancelled)
125
127
  end
126
128
 
127
129
  expect(input.monitor.interests).to be == :r
@@ -140,7 +142,7 @@ RSpec.describe Async::Wrapper do
140
142
  reactor.async do
141
143
  expect do
142
144
  input.wait_readable
143
- end.to raise_error(Async::Wrapper::Cancelled)
145
+ end.to raise_exception(Async::Wrapper::Cancelled)
144
146
  end
145
147
 
146
148
  expect(input.monitor.interests).to be == :r
@@ -148,7 +150,7 @@ RSpec.describe Async::Wrapper do
148
150
  reactor.async do
149
151
  expect do
150
152
  input.wait_readable
151
- end.to raise_error(Async::Wrapper::WaitError)
153
+ end.to raise_exception(Async::Wrapper::WaitError)
152
154
  end
153
155
  end
154
156
  end
@@ -193,7 +195,7 @@ RSpec.describe Async::Wrapper do
193
195
 
194
196
  expect do
195
197
  output.wait_readable
196
- end.to raise_error(IOError, /closed stream/)
198
+ end.to raise_exception(IOError, /closed stream/)
197
199
  end
198
200
  end
199
201
  end
@@ -34,7 +34,7 @@ RSpec.describe Enumerator do
34
34
  # no fiber really used in internal iterator,
35
35
  # but let this test be here for completness
36
36
  ar = nil
37
- Async::Reactor.run do |task|
37
+ Async do |task|
38
38
  ar = enum(task).to_a
39
39
  end
40
40
  expect(ar).to be == [1, 2]
@@ -42,7 +42,7 @@ RSpec.describe Enumerator do
42
42
 
43
43
  it "should play well with Enumerator as external iterator", pending: "expected failure" do
44
44
  ar = []
45
- Async::Reactor.run do |task|
45
+ Async do |task|
46
46
  en = enum(task)
47
47
  ar << en.next
48
48
  ar << en.next
@@ -54,15 +54,15 @@ RSpec.describe Enumerator do
54
54
  end
55
55
 
56
56
  it "should play well with Enumerator.zip(Enumerator) method", pending: "expected failure" do
57
- Async::Reactor.run do |task|
57
+ Async do |task|
58
58
  ar = [:a, :b, :c, :d].each.zip(enum(task))
59
59
  expect(ar).to be == [[:a, 1], [:b, 2], [:c, nil], [:d, nil]]
60
- end
60
+ end.wait
61
61
  end
62
62
 
63
63
  it "should play with explicit Fiber usage", pending: "expected failure" do
64
64
  ar = []
65
- Async::Reactor.run do |task|
65
+ Async do |task|
66
66
  fib = Fiber.new {
67
67
  Fiber.yield 1
68
68
  task.sleep(0.002)
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.12.0
4
+ version: 1.13.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: 2018-12-20 00:00:00.000000000 Z
11
+ date: 2019-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -131,6 +131,7 @@ files:
131
131
  - lib/async/reactor.rb
132
132
  - lib/async/semaphore.rb
133
133
  - lib/async/task.rb
134
+ - lib/async/terminal.rb
134
135
  - lib/async/version.rb
135
136
  - lib/async/wrapper.rb
136
137
  - logo.png
@@ -171,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
172
  - !ruby/object:Gem::Version
172
173
  version: '0'
173
174
  requirements: []
174
- rubygems_version: 3.0.0.beta3
175
+ rubygems_version: 3.0.1
175
176
  signing_key:
176
177
  specification_version: 4
177
178
  summary: Async is an asynchronous I/O framework based on nio4r.