Skip to content

Issues with RetryWhen #148

Open
Open
@Kn1kt

Description

@Kn1kt

Now RetryWhen subscribes to upstream twice. This is because the Sink itself subscribes to the upstream in .init.
Test testSuccessfulRetry() checks the number of subscriptions, but not correctly. It should check that the error publisher produces at least one item.

The correct test should look like this:

func testSuccessfulRetry() {
        var times = 0
        var retriesCount = 0
        
        var expectedOutput: Int?
        
        var completion: Subscribers.Completion<RetryWhenTests.MyError>?

        subscription = Deferred(createPublisher: { () -> AnyPublisher<Int, MyError> in
            defer { times += 1 }
            if times == 0 {
                return Fail<Int, MyError>(error: MyError.someError).eraseToAnyPublisher()
            }
            else {
                return Just(5).setFailureType(to: MyError.self).eraseToAnyPublisher()
            }
        })
        .retryWhen { error in
            error
                .handleEvents(receiveOutput: { _ in retriesCount += 1})
                .map { _ in }
        }
        .sink(
            receiveCompletion: { completion = $0 },
            receiveValue: { expectedOutput = $0 }
        )

        XCTAssertEqual(
            expectedOutput,
            5
        )
        XCTAssertEqual(completion, .finished)
        XCTAssertEqual(times, 2)
        XCTAssertEqual(retriesCount, 1)
    }

A possible solution is to remove upstream subscription from Sink.init and setting upstreamIsCancelled cancelUpstream function.

private let lock = NSRecursiveLock()


/// ...

func cancelUpstream() {
    lock.lock()
    guard !upstreamIsCancelled else {
        lock.unlock()
        return
    }
    upstreamIsCancelled = true
    lock.unlock()
    
    upstreamSubscription.kill()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions