Skip to content

Commit 8f7dfa1

Browse files
committed
Fix Future#flat when failures happen
1 parent d15c5d6 commit 8f7dfa1

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

lib/concurrent/edge/future.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,17 +1141,24 @@ def blocked_by
11411141

11421142
def process_on_done(future)
11431143
countdown = super(future)
1144-
value = future.value!
11451144
if countdown.nonzero?
1145+
internal_state = future.internal_state
1146+
1147+
unless internal_state.success?
1148+
complete_with internal_state
1149+
return countdown
1150+
end
1151+
1152+
value = internal_state.value
11461153
case value
11471154
when Future
11481155
@BlockedBy.push value
11491156
value.add_callback :pr_callback_notify_blocked, self
11501157
@Countdown.value
11511158
when Event
1152-
raise TypeError, 'cannot flatten to Event'
1159+
evaluate_to(lambda { raise TypeError, 'cannot flatten to Event' })
11531160
else
1154-
raise TypeError, "returned value #{value.inspect} is not a Future"
1161+
evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" })
11551162
end
11561163
end
11571164
countdown
@@ -1174,6 +1181,10 @@ def clear_blocked_by!
11741181
@BlockedBy.clear
11751182
nil
11761183
end
1184+
1185+
def completable?(countdown)
1186+
!@Future.internal_state.completed? && super(countdown)
1187+
end
11771188
end
11781189

11791190
# @!visibility private

spec/concurrent/edge/future_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,16 @@
312312
it 'has flat map' do
313313
f = Concurrent.future { Concurrent.future { 1 } }.flat.then(&:succ)
314314
expect(f.value!).to eq 2
315+
316+
err = StandardError.new('boo')
317+
f = Concurrent.future { Concurrent.failed_future(err) }.flat
318+
expect(f.reason).to eq err
319+
320+
f = Concurrent.future { raise 'boo' }.flat
321+
expect(f.reason.message).to eq 'boo'
322+
323+
f = Concurrent.future { 'boo' }.flat
324+
expect(f.reason).to be_an_instance_of TypeError
315325
end
316326
end
317327

0 commit comments

Comments
 (0)