CombineExt icon indicating copy to clipboard operation
CombineExt copied to clipboard

Unexplainable behavior of share-replay operator

Open troupmar opened this issue 2 years ago • 1 comments

Hello,

I have used share(reply:) operator in the past and just now I have encountered a corner case scenario, where it seems not to be working for some reason. I cannot say it is a problem of the share(replay) operator per se since I do not completely understand what and where the problem is.

Here is a simple failing test:

  func testShareOperator() {
    let expectation = self.expectation(description: "")

    let publisher = Just("random-test-string")

    let sharedPublisher = publisher.share(replay: 1)

    let downstream1 = sharedPublisher
    let downstream2 = sharedPublisher

    Publishers.Zip(downstream1, downstream2)
      .sink { _ in
        expectation.fulfill()
      }
      .store(in: &self.subscriptions)

    waitForExpectations(timeout: 1)
  }

For some reason the Zip operator "freezes" and does not deliver the expected value.

If the publisher is given a tiny delay, the test passes. I guess a thread hop is needed for the value to get through. However I do not understand why.

    let publisher = Just("random-test-string")
      .delay(for: 0.00000000001, scheduler: DispatchQueue.main)

Zip is not the only operator that does not work for me. I am facing the same problem if using CombineLatest instead. However the Concatenate operator, for example, does not have the same problem. I am guessing there is a problem with how (concurrently?) the downstream publishers are being fired in the operator. That is really my only clue.

Maybe I am missing something basic and if so, I am sorry for opening the issue. But I have been really struggling to understand what is going on and any help is appreciated!

Best, Martin

troupmar avatar Feb 24 '22 19:02 troupmar

Here is a possible solution: https://github.com/CombineCommunity/CombineExt/pull/120.

troupmar avatar Mar 22 '22 14:03 troupmar