1

I'd like to implement "scheduler inheritance" as part of an RxJava2-using API. I want consumers of my API to be able to think in terms of building a single processing chain rather than a DAG, even though, internally, new events are being teed in as an implementation detail.

I don't see any way to do the equivalent of:

observable
.flatMap {
  val scheduler = Schedulers().current!!
  someOtherObservable
    .observeOn(scheduler)
}

Is there some other way to inherit a scheduler?

More Context

I have a pipeline like:

compositeDisposable += Environment
  .lookupDeviceInfo()
  .subscribeOn(scheduler)
  .flatMap { deviceInfo ->
    Device(deviceId = deviceInfo.id)
      .sendCommand()
  .subscribe(
    { result -> /*process result*/ },
    { e -> /*log error*/ })

To the consumer, this looks like they pushed all the work onto the specified scheduler: events from lookupDeviceInfo() get vectored to a worker from that scheduler, and they expect to stick on that worker.

In practice, they have a bug, because sendCommand() tees in events from another event source as an implementation detail:

sendMessageSingle(deviceId, payload)
.flatMap { sentMessageId ->
  responseObservable
  .filter { it.messageId == sentMessageId }
  .firstOrError()
}

Events stream in from responseObservable, but none of those events get vectored to the specified scheduler, because that got applied upstream.

Jeremy W. Sherman
  • 35,901
  • 5
  • 77
  • 111
  • Returning to the same scheduler thread requires you to provide a single-threaded scheduler (i.e., `Schedulers.from(Executor)`, `Schedulers.single()`, etc.). There is no current scheduler because there is no guarantee some code will run on any of the standard schedulers; they could be executing on arbitrary threads of the system, other frameworks, etc. Thus, you have to route the signals back to the desired thread via `observeOn`. – akarnokd Sep 25 '18 at 08:02
  • @akarnokd I'm not concerned about landing on the same _thread_, just the same _scheduler._ (Even changing Workers may be fine, so long as the new worker is vended by the same scheduler as the old.) – Jeremy W. Sherman Sep 25 '18 at 14:54
  • Then the suggestion still applies and you can forego the "single-threaded" property I mentioned. – akarnokd Sep 25 '18 at 14:59
  • @akarnokd Ah, I see now. The key part for me was the bit about how the question doesn't even make sense, because there is no such thing as a current scheduler, because you aren't necessarily using any scheduler. If you transplant your comments to an answer, I'd be happy to accept it. :) – Jeremy W. Sherman Oct 03 '18 at 15:47

1 Answers1

1

From the comments:

Returning to the same scheduler thread requires you to provide a single-threaded scheduler (i.e., Schedulers.from(Executor), Schedulers.single(), etc.). There is no current scheduler because there is no guarantee some code will run on any of the standard schedulers; they could be executing on arbitrary threads of the system, other frameworks, etc. Thus, you have to route the signals back to the desired thread via observeOn.

I'm not concerned about landing on the same thread, just the same scheduler. (Even changing Workers may be fine, so long as the new worker is vended by the same scheduler as the old.)

Then the suggestion still applies and you can forego the "single-threaded" property I mentioned.

akarnokd
  • 69,132
  • 14
  • 157
  • 192