我从Monix firstOptionL中获得不一致的结果-竞赛条件?

时间:2019-06-28 10:11:09

标签: scala monix

通过重复调用相同的(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。

0 个答案:

没有答案