Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using RxGRDB with TestScheduler #22

Closed
davidkraus opened this issue Feb 23, 2018 · 5 comments
Closed

Using RxGRDB with TestScheduler #22

davidkraus opened this issue Feb 23, 2018 · 5 comments

Comments

@davidkraus
Copy link

Hey,
is there a reason why the scheduler overloads are restricted to a SerialDispatchQueueScheduler?
I want to setup a unit test with an inMemory SQLite GRDB instance and somehow i can't get it to work. I'm not too familiar with GRDB/Scheduler internals so i don't know if this is even possible? Do you have any thoughts on this?

@groue
Copy link
Collaborator

groue commented Feb 23, 2018

Hello @davidkraus

I'm not familiar enough with schedulers to answer your question yet. We're both RxSwift schedulers newbies :-)

I know that SerialDispatchQueueScheduler provides the kind of guarantees that RxGRDB needs. But a more general protocol may still honor the very strict scheduling requirements of SQLite. I'll need to have a look.

@groue
Copy link
Collaborator

groue commented Feb 25, 2018

OK @davidkraus, let's investigate what those schedulers are 🤘

The Schedulers documentation is useful, but also not very clear. There are sentences like the following, which is impossible to understand:

In case the scheduler is concurrent, Rx's observeOn and subscribeOn operators will make sure everything works perfectly.

Thank you, but I'd like to know what this "perfection" is about ;-) The ReactiveX page on Schedulers does not bring more information.

Either you're not supposed to know what a scheduler really is, or schedulers are very hard to describe. Maybe there is a reference somewhere, which aims at helping the various ReactiveX implementations being compatible, but I could not find it.

Fortunately, there are hints in RxSwift doc that the fundamental job of RxSwift schedulers is to execute single-threaded "actions", one at a time, and that actions can not be reentrantly nested (one action can not be part of another one):

If you use some scheduler that Rx can prove is serial, it will be able to perform additional optimizations.

If some parent frame on the call stack is already running CurrentThreadScheduler.instance.schedule(state) { }, the scheduled action will be enqueued and executed when the currently running action and all previously enqueued actions have finished executing.

I don't know if this guarantee is particular to RxSwift, an implementation detail, or if this is true for all ReactiveX schedulers in general.


Now let's look at the two available Scheduler protocols: ImmediateSchedulerType, and SchedulerType.

They can schedule actions "immediately", "relatively", "periodically", or "recursively". My interpretations:

  • "immediately" has an action enqueued for being executed as soon as possible.
  • "relatively" has an action enqueued for being executed after a delay.
  • "periodically" deals with timers.
  • "recursively" deals with tail recursion.

There's still nothing that defines what a scheduler is, but there is nothing that invalidates the hypothesis that "schedulers execute single-threaded actions, one at a time, and avoid reentrancy".


I think we'll need @kzaher to know, for good, what is the scheduler contract.


But I have enough information now for answering your question 😄

Since RxGRDB, as far as I know, just needs serial execution (the guarantee that no two scheduled actions overlap), I can replace SerialDispatchQueueScheduler with ImmediateSchedulerType in the RxGRDB APIs.

A new release will ship shortly. And thanks for your question!

@groue
Copy link
Collaborator

groue commented Feb 25, 2018

Done, you can use any scheduler you want with RxGRDB v0.9.0.

@davidkraus
Copy link
Author

Wow thanks, you are fast ;).
I just tested our code with v0.9.0 and it works now 🎉.

Ok so the Scheduler thing: As far as i understand it the Scheduler does not magically introduce any kind of concurrency - And i think they can't because this would interfere with the Observable contract (onNext sequentially and on the same thread). If you want to parallelise your code you have to use a combination of flatMap and observeOn (see https://tomstechnicalblog.blogspot.de/2015/11/rxjava-achieving-parallelization.html).

@groue
Copy link
Collaborator

groue commented Feb 26, 2018

David, you're totally right! The contract I have been looking for in schedulers was actually defined on observables themselves :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants