async 1.12.0 → 1.13.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.
@@ -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.