Skip to content

Commit 4fc87f8

Browse files
committed
Add documentation for zipping of failures
1 parent 89a6f29 commit 4fc87f8

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

examples/edge_futures.in.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
Concurrent.future { Object.new }.then(&:succ).rescue { 1 }.then(&:succ).value
3636
Concurrent.future { 1 }.then(&:succ).rescue { |e| e.message }.then(&:succ).value
3737

38+
failing_zip = Concurrent.completed_future(1) & Concurrent.future { raise 'boom' }
39+
failing_zip.result
40+
failing_zip.then { |v| 'never happens' }.result
41+
failing_zip.rescue { |a, b| (a || b).message }.value
42+
failing_zip.chain { |success, values, reasons| [success, values.compact, reasons.compactß] }.value
3843

3944
### Delay
4045

examples/edge_futures.out.rb

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
### Simple asynchronous task
22

33
future = Concurrent.future { sleep 0.1; 1 + 1 } # evaluation starts immediately
4-
# => <#Concurrent::Edge::Future:0x7fd41a956d70 pending blocks:[]>
4+
# => <#Concurrent::Edge::Future:0x7fc6218f2318 pending blocks:[]>
55
future.completed? # => false
66
# block until evaluated
77
future.value # => 2
@@ -11,7 +11,7 @@
1111
### Failing asynchronous task
1212

1313
future = Concurrent.future { raise 'Boom' }
14-
# => <#Concurrent::Edge::Future:0x7fd41a946c18 failed blocks:[]>
14+
# => <#Concurrent::Edge::Future:0x7fc6218eae38 pending blocks:[]>
1515
future.value # => nil
1616
future.value! rescue $! # => #<RuntimeError: Boom>
1717
future.reason # => #<RuntimeError: Boom>
@@ -41,26 +41,34 @@
4141
Concurrent.future { 1 }.then(&:succ).rescue { |e| e.message }.then(&:succ).value
4242
# => 3
4343

44+
failing_zip = Concurrent.completed_future(1) & Concurrent.future { raise 'boom' }
45+
# => <#Concurrent::Edge::Future:0x7fc6218b0f08 pending blocks:[]>
46+
failing_zip.result # => [false, [1, nil], [nil, #<RuntimeError: boom>]]
47+
failing_zip.then { |v| 'never happens' }.result # => [false, [1, nil], [nil, #<RuntimeError: boom>]]
48+
failing_zip.rescue { |a, b| (a || b).message }.value
49+
# => "boom"
50+
failing_zip.chain { |success, values, reasons| [success, values.compact, reasons.compactß] }.value
51+
# => nil
4452

4553
### Delay
4654

4755
# will not evaluate until asked by #value or other method requiring completion
4856
future = Concurrent.delay { 'lazy' }
49-
# => <#Concurrent::Edge::Future:0x7fd41a8f6ec0 pending blocks:[]>
57+
# => <#Concurrent::Edge::Future:0x7fc6218a37e0 pending blocks:[]>
5058
sleep 0.1
5159
future.completed? # => false
5260
future.value # => "lazy"
5361

5462
# propagates trough chain allowing whole or partial lazy chains
5563

5664
head = Concurrent.delay { 1 }
57-
# => <#Concurrent::Edge::Future:0x7fd41a8ee1a8 pending blocks:[]>
65+
# => <#Concurrent::Edge::Future:0x7fc6218a0720 pending blocks:[]>
5866
branch1 = head.then(&:succ)
59-
# => <#Concurrent::Edge::Future:0x7fd41a8ed438 pending blocks:[]>
67+
# => <#Concurrent::Edge::Future:0x7fc6212c7b50 pending blocks:[]>
6068
branch2 = head.delay.then(&:succ)
61-
# => <#Concurrent::Edge::Future:0x7fd41a8e7588 pending blocks:[]>
69+
# => <#Concurrent::Edge::Future:0x7fc6212c6098 pending blocks:[]>
6270
join = branch1 & branch2
63-
# => <#Concurrent::Edge::Future:0x7fd41a8e4ec8 pending blocks:[]>
71+
# => <#Concurrent::Edge::Future:0x7fc6212c4f40 pending blocks:[]>
6472

6573
sleep 0.1 # nothing will complete # => 0
6674
[head, branch1, branch2, join].map(&:completed?) # => [false, false, false, false]
@@ -88,14 +96,14 @@
8896
### Schedule
8997

9098
scheduled = Concurrent.schedule(0.1) { 1 }
91-
# => <#Concurrent::Edge::Future:0x7fd41a8a4468 pending blocks:[]>
99+
# => <#Concurrent::Edge::Future:0x7fc62128c550 pending blocks:[]>
92100

93101
scheduled.completed? # => false
94102
scheduled.value # available after 0.1sec # => 1
95103

96104
# and in chain
97105
scheduled = Concurrent.delay { 1 }.schedule(0.1).then(&:succ)
98-
# => <#Concurrent::Edge::Future:0x7fd41a895828 pending blocks:[]>
106+
# => <#Concurrent::Edge::Future:0x7fc6228bcdc0 pending blocks:[]>
99107
# will not be scheduled until value is requested
100108
sleep 0.1
101109
scheduled.value # returns after another 0.1sec # => 2
@@ -104,36 +112,36 @@
104112
### Completable Future and Event
105113

106114
future = Concurrent.future
107-
# => <#Concurrent::Edge::CompletableFuture:0x7fd41a87c648 pending blocks:[]>
115+
# => <#Concurrent::Edge::CompletableFuture:0x7fc623083720 pending blocks:[]>
108116
event = Concurrent.event
109-
# => <#Concurrent::Edge::CompletableEvent:0x7fd41a8770d0 pending blocks:[]>
117+
# => <#Concurrent::Edge::CompletableEvent:0x7fc623081100 pending blocks:[]>
110118
# Don't forget to keep the reference, `Concurrent.future.then { |v| v }` is incompletable
111119

112120
# will be blocked until completed
113121
t1 = Thread.new { future.value }
114122
t2 = Thread.new { event.wait }
115123

116124
future.success 1
117-
# => <#Concurrent::Edge::CompletableFuture:0x7fd41a87c648 success blocks:[]>
125+
# => <#Concurrent::Edge::CompletableFuture:0x7fc623083720 success blocks:[]>
118126
future.success 1 rescue $!
119127
# => #<Concurrent::MultipleAssignmentError: Future can be completed only once. Current result is [true, 1, nil], trying to set [true, 1, nil]>
120128
future.try_success 2 # => false
121129
event.complete
122-
# => <#Concurrent::Edge::CompletableEvent:0x7fd41a8770d0 completed blocks:[]>
130+
# => <#Concurrent::Edge::CompletableEvent:0x7fc623081100 completed blocks:[]>
123131

124132
[t1, t2].each &:join
125133

126134

127135
### Callbacks
128136

129-
queue = Queue.new # => #<Thread::Queue:0x007fd41b0543e8>
137+
queue = Queue.new # => #<Thread::Queue:0x007fc62127df00>
130138
future = Concurrent.delay { 1 + 1 }
131-
# => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
139+
# => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
132140

133141
future.on_success { queue << 1 } # evaluated asynchronously
134-
# => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
142+
# => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
135143
future.on_success! { queue << 2 } # evaluated on completing thread
136-
# => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
144+
# => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
137145

138146
queue.empty? # => true
139147
future.value # => 2
@@ -144,15 +152,15 @@
144152
### Thread-pools
145153

146154
Concurrent.future(:fast) { 2 }.then(:io) { File.read __FILE__ }.wait
147-
# => <#Concurrent::Edge::Future:0x7fd41a857550 success blocks:[]>
155+
# => <#Concurrent::Edge::Future:0x7fc62125d9a8 success blocks:[]>
148156

149157

150158
### Interoperability with actors
151159

152160
actor = Concurrent::Actor::Utils::AdHoc.spawn :square do
153161
-> v { v ** 2 }
154162
end
155-
# => #<Concurrent::Actor::Reference:0x7fd41c03b5b8 /square (Concurrent::Actor::Utils::AdHoc)>
163+
# => #<Concurrent::Actor::Reference:0x7fc621234a30 /square (Concurrent::Actor::Utils::AdHoc)>
156164

157165
Concurrent.
158166
future { 2 }.
@@ -165,32 +173,32 @@
165173

166174
### Interoperability with channels
167175

168-
ch1 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fd41a297458>
169-
ch2 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fd41a296940>
176+
ch1 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fc621205460>
177+
ch2 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fc6212041c8>
170178

171179
result = Concurrent.select(ch1, ch2)
172-
# => <#Concurrent::Edge::CompletableFuture:0x7fd41a295c98 pending blocks:[]>
180+
# => <#Concurrent::Edge::CompletableFuture:0x7fc6211fe5c0 pending blocks:[]>
173181
ch1.push 1 # => nil
174182
result.value!
175-
# => [1, #<Concurrent::Edge::Channel:0x007fd41a297458>]
183+
# => [1, #<Concurrent::Edge::Channel:0x007fc621205460>]
176184

177185
Concurrent.
178186
future { 1+1 }.
179187
then_push(ch1)
180-
# => <#Concurrent::Edge::Future:0x7fd41a284010 pending blocks:[]>
188+
# => <#Concurrent::Edge::Future:0x7fc6211f7338 pending blocks:[]>
181189
result = Concurrent.
182190
future { '%02d' }.
183191
then_select(ch1, ch2).
184192
then { |format, (value, channel)| format format, value }
185-
# => <#Concurrent::Edge::Future:0x7fd41a25d938 pending blocks:[]>
193+
# => <#Concurrent::Edge::Future:0x7fc6211ec668 pending blocks:[]>
186194
result.value! # => "02"
187195

188196

189197
### Common use-cases Examples
190198

191199
# simple background processing
192200
Concurrent.future { do_stuff }
193-
# => <#Concurrent::Edge::Future:0x7fd41a23d520 pending blocks:[]>
201+
# => <#Concurrent::Edge::Future:0x7fc6211df170 pending blocks:[]>
194202

195203
# parallel background processing
196204
jobs = 10.times.map { |i| Concurrent.future { i } }
@@ -207,7 +215,7 @@ def schedule_job
207215
end # => :schedule_job
208216

209217
schedule_job
210-
# => <#Concurrent::Edge::Future:0x7fd41a2245e8 pending blocks:[]>
218+
# => <#Concurrent::Edge::Future:0x7fc62119c140 pending blocks:[]>
211219
@end = true # => true
212220

213221

@@ -220,7 +228,7 @@ def schedule_job
220228
data[message]
221229
end
222230
end
223-
# => #<Concurrent::Actor::Reference:0x7fd41a206228 /db (Concurrent::Actor::Utils::AdHoc)>
231+
# => #<Concurrent::Actor::Reference:0x7fc62117f568 /db (Concurrent::Actor::Utils::AdHoc)>
224232

225233
concurrent_jobs = 11.times.map do |v|
226234
Concurrent.
@@ -250,7 +258,7 @@ def schedule_job
250258
end
251259
end
252260
end
253-
# => #<Concurrent::Actor::Reference:0x7fd41a0530c0 /DB-pool (Concurrent::Actor::Utils::Pool)>
261+
# => #<Concurrent::Actor::Reference:0x7fc6218969f0 /DB-pool (Concurrent::Actor::Utils::Pool)>
254262

255263
concurrent_jobs = 11.times.map do |v|
256264
Concurrent.

0 commit comments

Comments
 (0)