Skip to content

Commit 892b818

Browse files
committed
Amb: forward cancel to the inner publishers
We noticed that cancelling an Amb publisher does not cancel any of the inner publishers. It looks like nil-ing firstSink / secondSink should do the job, but it does not work. Adding explicit cancel fixes the issue, but I’m not sure if this is the right solution.
1 parent aaf1a09 commit 892b818

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

Sources/Operators/Amb.swift

+2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ private extension Publishers.Amb {
144144
}
145145

146146
func cancel() {
147+
firstSink?.cancelUpstream()
147148
firstSink = nil
149+
secondSink?.cancelUpstream()
148150
secondSink = nil
149151
}
150152
}

Tests/AmbTests.swift

+31
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,37 @@ class AmbTests: XCTestCase {
4747
XCTAssertEqual(completion, .finished)
4848
}
4949

50+
func testAmbCancelPreSubscription() {
51+
enum CancelError: Swift.Error {
52+
case cancelled
53+
}
54+
var ambPublisher: AnyCancellable?
55+
56+
var firstCompletion: Subscribers.Completion<CancelError>?
57+
let subject1 = PassthroughSubject<Int, CancelError>()
58+
let subject1Publisher = subject1
59+
.handleEvents(receiveCancel: {
60+
firstCompletion = .failure(CancelError.cancelled)
61+
})
62+
.eraseToAnyPublisher()
63+
64+
var secondCompletion: Subscribers.Completion<CancelError>?
65+
let subject2 = PassthroughSubject<Int, CancelError>()
66+
let subject2Publisher = subject2
67+
.handleEvents(receiveCancel: {
68+
secondCompletion = .failure(CancelError.cancelled)
69+
})
70+
.eraseToAnyPublisher()
71+
72+
ambPublisher = Publishers.Amb(first: subject1Publisher, second: subject2Publisher)
73+
.sink(receiveCompletion: { _ in },
74+
receiveValue: { _ in })
75+
ambPublisher?.cancel()
76+
77+
XCTAssertEqual(firstCompletion, .failure(CancelError.cancelled))
78+
XCTAssertEqual(secondCompletion, .failure(CancelError.cancelled))
79+
}
80+
5081
func testAmbLimitedPreDemand() {
5182
let subject1 = PassthroughSubject<Int, Never>()
5283
let subject2 = PassthroughSubject<Int, Never>()

0 commit comments

Comments
 (0)