Hi, I was able to create an example that does not use any receiveOn or multi-threading/concurrency that shows indeterministic behavior. I am wondering if that is a bug. I already filed as FB9108105 but I am curious to hear your thoughts.
I have two subjects 1 and 2 and marble-style emitting looks like this
A: 1 2 3
B: X
I was actually looking for a publisher that combinesLatest but buffers the „missed“ values from A, so that I get (1,X), (2,X), (3,X). Original question here: ios - Elegant way to combineLatest without dropping values and imbalanced publishers in Swift Combine - Stack Overflow
While looking for a solution, I found one that buffers the values of both subjects until the other one emits the first value. However, I am seeing indeterministic behavior. Sometimes, I get (2,X), (3,X) and sometimes (1,X), (2,X), (3,X). Since my solutions does not involve any receiveOn, I would expect to see either or and that consistently.
Here is the minimal example. It will output how often the sink sees 3 values and how often 2.
import UIKit
import Combine
func runExperimentAndReturnNumberOfValuesInSink() -> Int {
var resultingValues:Int = 0
let subject1 = PassthroughSubject<Int, Never>()
let subject2 = PassthroughSubject<String, Never>()
let bufferedSubject1 = Publishers.Concatenate(prefix: Publishers.PrefixUntilOutput(upstream: subject1, other: subject2).collect().flatMap(\.publisher),
suffix: subject1)
let bufferedSubject2 = Publishers.Concatenate(prefix: Publishers.PrefixUntilOutput(upstream: subject2, other: subject1).collect().flatMap(\.publisher),
suffix: subject2)
let combined = Publishers.CombineLatest(bufferedSubject1, bufferedSubject2)
let cancelable = combined.collect()
.sink(receiveValue: { v in
resultingValues = v.count
})
subject1.send(1)
subject1.send(2)
subject2.send("X")
subject2.send(completion: .finished)
subject1.send(3)
subject1.send(completion: .finished)
return resultingValues
}
var retrievedValues = [2: 0, 3:0]
for _ in (1...100) {
retrievedValues[runExperimentAndReturnNumberOfValuesInSink()]! += 1
}
print("If the behavior was deterministic, we would expect 100 runs with the same output.")
print(retrievedValues)