1

I can't figure out why adding executeWithFork prevents task from running in the following example:

import java.util.concurrent.TimeUnit

import monix.execution.schedulers.SchedulerService
import monix.reactive.subjects.ConcurrentSubject

object Sandbox {

  def main(args: Array[String]): Unit = {
    implicit val scheduler: SchedulerService =
      monix.execution.Scheduler(java.util.concurrent.Executors.newCachedThreadPool())

    val input = ConcurrentSubject.publish[String]

    // prints nothing
    input.foreachL(println).executeWithFork.runAsync
    // this works:
    // input.foreachL(println).runAsync

    input.onNext("one")
    input.onNext("two")

    scheduler.shutdown()
    scheduler.awaitTermination(1, TimeUnit.MINUTES, monix.execution.Scheduler.Implicits.global)
  }
}
eprst
  • 733
  • 6
  • 14

1 Answers1

1

The behavior you see is a result of two facts:

  1. using executeWithFork introduce a bit of additional latency for thread switch

  2. you use ConcurrentSubject.publish (as opposed to replay for example). If you open the docs for PublishSubject you may see that

A PublishSubject emits to a subscriber only those items that are emitted by the source subsequent to the time of the subscription.

In other words you have a race condition between the main thread that publishes the "one" and "two" and the forked thread that has to subscribe to the input to get the data. Results depends on which thread wins the race: all the data published before the subscription is lost. One my hardware I almost always see "two" and very occasionally even see "one", your results might vary.

The simplest way to test this is to add Thread.sleep(100) before the first input.onNext and you should see both events printed every time. You may also try to push more events than just 2 to see that not everything is lost.

SergGr
  • 23,570
  • 2
  • 30
  • 51