通过重复调用相同的(MongoDB)数据库调用,我得到了一个间歇性的丢失值,该数据库调用已转换为Observable。我删除了所有数据库代码,以获取仅包含Monix位的最小测试用例,而且我偶尔仍然缺少值-通常每2,000个测试中有一个或两个。
根据文档ConcurrentSubject的意思是“不需要遵循背压合同”,但是无论是否进行,我都会遇到类似的失败。
import monix.eval.Task
import monix.reactive.{MulticastStrategy, Observable}
import monix.reactive.subjects.ConcurrentSubject
import org.scalatest.FunSuite
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class Test_JustMonix extends FunSuite {
implicit val scheduler = monix.execution.Scheduler.global
def build(): Observable[Boolean] = {
val subject = ConcurrentSubject(MulticastStrategy.publish[Boolean])
subject.doAfterSubscribe {
Task.eval {
subject.onNext(true)
subject.onComplete()
}
}
}
test("just monix") {
(0 until 20).foreach { loop =>
println(s"loop $loop")
val tOpts = (0 until 100).map { _ => build().firstOptionL }
val tDone = Task.gather(tOpts).map { list =>
val emptyCount = list.count(_.isEmpty)
assert(emptyCount === 0)
}
Await.result(tDone.runToFuture, Duration.Inf)
}
println("Finished")
}
}
在某些运行中,所有20x100循环均正确完成-为所有2,000个结果定义了firstOptionL。但是,当值是1或有时是2时,assert(emptyCount === 0)触发的时间超过50%,这表明我偶尔会得到None值,就像onComplete发生在onNext之前一样。
这可能会在20个循环中的任何一个中发生,因此看起来好像是竞争情况,或者我误解了所需的输入。我已经尝试了几乎所有主题-PublishSubject,使用和不使用BufferedSubscriber都可以得到相似的结果。
我还尝试通过以下方式将onComplete延迟到Ack为止
subject.onNext(true).map(_=> subject.onComplete())
那似乎很快就会失败。
我也尝试了MulticastStrategy.replay,没有区别。
我正在Scala 2.12.8上使用Monix 3.0.0-RC3。