How many "temperatures" are there for a Rx Observable? - rxjs

All over the Rx.Net literature there are references to what is commonly know as the temperature of an observable.
There are cold observables (like the ones created by Observable.Interval() and similar factory methods), which will create side effects every time that a new Subscription is created.
On the other side of the spectrum there are hot observables (like Subject<T>) which will onboard new subscriptions as they come.
There are also warm observables, like the ones returned by RefCount() which will execute the initialisation every time one subscription is created, but only if there was no other active subscription. The behaviour of these warm observables is explained here by Dave Sexton:
Alternatively, you can call Publish then RefCount to get an IObservable that is shared among multiple consecutive observers. Note that this isn't truly a hot observable - it's more like a warm observable. RefCount makes a single subscription to the underlying observable while there's at least one observer of your query. When your query has no more observers, changing the reference count to 0, the underlying subscription is disposed. If another observer subscribes to your query later, moving the reference count from 0 to 1 again, then RefCount makes a new subscription to the underlying observable, causing subscription side-effects to occur again.
Are there any other temperatures that one should be aware of? Is it possible to obtain programmatically the temperature of an Observable?

Easy question first:
Is it possible to obtain programmatically the temperature of an Observable?
No. Best you can do is subscribe and see what happens.
The observable 'contract' specifies that when you subscribe to an observable you get zero or more OnNext messages, optionally followed by either one OnCompleted or one OnError message. The contract doesn't specify anything about how multiple or earlier/later subscribers are treated, which is what observable 'temperature' is mostly concerned with.
Are there any other temperatures that one should be aware of?
I wouldn't even think of it in such concrete or discrete terms as you have specified.
I think of it in terms of on-subscribe effects: The coldest of observables have all their effects happen on subscribe (like Observable.Return(42)). The hottest of observables have no effects happening on subscribe (new Subject<int>()). In between those two poles is a continuum.
Observable.Interval(TimeSpan.FromMilliseconds(100)) for example will emit a new number every 100 milliseconds. That example, unlike Observable.Return(42), could be mostly 'warmed-over' via .Publish().RefCount(): The first subscriber starts the numbers, but the second subscriber will see the only the latest numbers, not starting from 0. However, if instead of .Publish() you did .Replay(2).RefCount(), then you have some on-subscribe effects going on. Do the Publish and Replay observables have the same 'temperature'?
TL;DR: Don't focus on the classifications that much. Understand the difference between the two and know that some observables have colder properties and some have warmer ones.

Related

Does RxJS `share` operator really makes an Observable hot?

The documentation of a share operator states that:
As long as there is at least one Subscriber this Observable will be subscribed and emitting data. ... Because the Observable is multicasting it makes the stream hot
I thought that hot observable is the one that starts emitting data without a need to be subscribed to?
Am I wrong?
You've misunderstood what hot and cold observables are.
Cold Observable
In RxJS an observable is cold (also known as unicasted), when there is one source per subscriber. When subscribing to a cold source, the pipeline gets recreated for each subscriber. Note the following: if your pipeline is computation heavy, then you'd be doing that computation everytime a new subscriber subscribes to that source.
Hot Observable
In RxJS an observable is hot (also known as multicasting), when there is one source for all subscribers. When subscribing to a hot source, the pipeline doesn't get recreated for each subscriber. Hot sources are useful for when you don't want to compute the pipeline for every subscriber. The pipeline will be computed once, and then the answer will be sent to all subscribers.
StackBlitz Example showing this in code.
Yes, hot observables emit data even when no subscriber is active just like a websocket or mouse events. They are independent of subscribers.
Cold observables emit data only when subscribed to it, e.g. without subscribing to an obervable wrapping a http request, your http request will never happen.
Using share, your cold observable gets hot, as no new http request will happen but the old response will be remitted.

Expose a Subject to Callers But Be Notified when Subscriptions Drop to Zero

I have a service that I want to hand out a Subject (although it could be typed as an observable) as the result of a method call. This is straightforward, but what I really want is to be able to "detect" when its unsubscribe method is called (or since it could technically be handed out more than once to multiple subscribers, when its subscription count falls to zero). Is this possible?
If you take a look at the source code to a behavior subject
https://github.com/ReactiveX/rxjs/blob/master/src/internal/BehaviorSubject.ts
you will see how to extend a subject. You could do the same thing to create your own kind of subject that instead of taking a start value it takes a callback to be run on unsubscribe that passes in the observer count. You would need to return a custom subscription object as unsubscribe is done from the subscription.

Difference between RxJS and IxJS?

What's the difference between RxJS and IxJS, and when would I want to use one over the other?
From the IxJS docs:
RxJS is great for event-based workflows where the data can be pushed at the rate of the producer, however, IxJS is great at I/O operations where you as the consumer can pull the data when you are ready.
After going through the docs, the only major difference seems to be the concept of Iterables in IxJS and Observables in RxJS.
Both Iterables and Observables execute either synchronously or asynchronously, and the .forEach from IxJS is essentially the same as RxJS's .subscribe method when paired with the almost-identical from creator function. The only other difference is IxJS's .forEach method is optional because you could use the imperative for-of instead.
It seems like there are two libraries for no reason because RxJS's from creator function can convert Iterables to Observables.
From my perspective, it's not really IxJS and RxJS, it's Iterables and Observables. How are they different and when would you use one over the other?
tl;dr
RxJS processes values as soon as they arrive. It's a push system.
IxJS specifies when to pass in the next value. It's a pull system.
Explanation
IxJS may be helpful if want to have pull-based model, for example, when dealing with backpressure.
As you can see in the documentation:
IxJS unifies both synchronous and asynchronous pull-based collections, just as RxJS unified the world of push-based collections. RxJS is great for event-based workflows where the data can be pushed at the rate of the producer, however, IxJS is great at I/O operations where you as the consumer can pull the data when you are ready.
In other words:
Use RxJS if your producer (usually User) is slower that processing of data (this is common for frontend).
Use IxJS if your producer (usually System) is much faster than you can process data (more common for the backend).
To understand what this means, consider the following example:
You need to build ETL pipeline and process a large file (about 1TB).
If you write it with RxJS, something like:
readFileByLineObservable('path/to/file')
.pipe(
doSomeHeavyTransformation(),
)
.subscribe()
Then readFileByLineObservable will try to "push" the entire file of 1TB into RAM as soon as possible. Only after this occurs, you will start to do doSomeHeavyTransformation. This problem is called backpressure.
In contrast, IxJS will try to "pull" each newline only after previous line was processed. That's the optimal processing method in this case.
The difference is how RxJS's .subscribe sets up a listener whereas IxJS's .forEach tells its iterator when to give the next value (only after its done processing the first one. It's similar to, but not the same as, RxJS's concatMap and concatAll operators.
As a complement to Oles Savluk answer, I found Matt Podwysocki's explanation particularly useful (https://gist.github.com/mattpodwysocki/1d0fe43961c6222571386568b8a5ef23):
we have four types of collections, each with their own purpose. Each
has its own place, and there's no one solution that rules them all.
Pull: Iterable - purely synchronous data, either finite or infinite
Push: Observable / Subject/Observer - eventual data such as DOM events, collections over time
Pull/Push: AsyncIterable - I/O or other asynchronous data where the consumer needs to be in control
Push/Pull: AsyncObservable - Network calls where creation/teardown may be asynchronous as well as projections may be asynchronous too.
Matt is a contributor to both RxJS and IxJS.
Iterable and AsyncIterable come from IxJS, Observable and AsyncObservable are developed in RxJS

How to cache a reactive publisher like Observable?

I'm trying to understand what happens if I cache the result of a method returning a cold Observable? The flow has not been materialized yet, so what does the cache actually contain? I tried to find out using Hazelcast and Spring Boot but couldn't get the cache working.
Edit:
When I say cache not working, I am speaking based on what I see from Hazelcast Management Center. Depending on the cache config (I tried many things), either the cache shows up but no entries, or the cache doesn't show up at all.
Example:
#javax.cache.annotation.CacheResult
Observable<Integer> random() {
// Do I get a new number every time?
return Observable.just(new Random().nextInt());
}
From rx-java wiki (source here):
A cold Observable emits a particular sequence of items, but can begin
emitting this sequence when its Observer finds it to be convenient,
and at whatever rate the Observer desires, without disrupting the
integrity of the sequence. For example if you convert a static
Iterable into an Observable, that Observable will emit the same
sequence of items no matter when it is later subscribed to or how
frequently those items are observed. Examples of items emitted by a
cold Observable might include the results of a database query, file
retrieval, or web request.
With cold Observable, like your example, the request is done at subscribe time, for each subscriber. Even without cache, if you subscribe twice to the same Observable, the request will occur twice. The Observable is not bound to a specific stream. Observable is just a contract describing how to access data.
Caching the result of a method returning an Observable is I think somewhat similar to storing the result to a local property; you just avoid to recreate the Observable object again later. But just the 'getter', not the data.
rx-java give some tools to achieve caching by it's own. You could have a look to Subject or ConnectableObservable.

RxJava in trading engine

I'll write in pseudocode to avoid unnecessary boilerplate. I'm new to Rx but i really want to use it instead of Features and similar stuff...
this is a simplified model of trading engine
we have a which provides all the streams of events (observables) that one might be interested in like
market.updateStream // stream of orderbook update events
we have so called s those will subscribe to requried streams and "react" when any change occures like this
market.updateStream.subscribe(bot1.marketUpdateAction)
market.updateStream.subscribe(bot2.marketUpdateAction)
we might have MANY bots that will subscribe to ONE market and each of those will either start calculating or ignore the change event.
now that we have N bots reacting to 1 event, we need someone to compare their calculations and decide which one is the most profitable also if some bot is slowing down and is exceeding limit of time we are ready to wait, we skip it and proceed to comparision and execution... for that we have a botController which is subscribed to all bots events so that it knows when a bot decided to react to an event... like this
bot1.calculationStream.subscribe(botController.botActivityAction)
bot will in its turn emit 2 different events (calculationStarted and calculationEnded which contains actual result)
when a bot emits event that its started to calculate (this happens if market event is in bot interest so not all bots will emit start event) botController shall do the following, start counting time with the very first bot started event, and await for all bots that emit similar event, if registered bots finish early, comparision starts immidiately...
Sorry if the question is too abstract but i dont really see how do i implement botControllers behaviour with RxJava... Any toughts are appreciated... there are so many rx transformations that i dont really know what can i use there.
UPDATE
Suppose our controller is subscribed to N bots events and each bot can emit 2 events (STARTED, COMPLETED)...
now when controller gets first STARTED event its starts the countdown T, while T time is not expired it will accept new events from bots, when T is expired or all bots return COMPLETED event it does some calculation and returns a single result...
the part i dont understand : rx as far as i know is handling each event in isolation thus the safety from tipical concurrency problems, now that i have several events that are tied to each other i dont see how can i do this using rx... I just need some guidance on this.
I don't fully understand your problem, but here are some design ideas to show you how to think the "Rx-way":
I wouldn't subscribe bots, but rather, they should be a map or flatMap on the update stream, so that they transform the stream of updates into a stream of their answers.
I'd make a BotAnswer class with 4 subclasses: Result, NotInterested, Timeout, BotError.
Then for each bot:
Observable<BotAnswer> bot1Answers = market.updateStream.flatMap(event ->
Observable.just(event).map({ if (event is interesting)
return new Result(doBotCalculations())
else
return new NotInterested()
})
.timeout(T, TimeUnit.SECONDS)
.onErrorResumeNext(
error -> if (error instanceof TimeoutException)
return Observable.just(new Timeout())
else
return Observable.just(new BotError(error))
)
)
And the controller would do a zip on all bot answers:
Observable.zip(bot1Ansers, bot2Answers, ... (a1, a2, ...) -> {
// compare the answers a1, a2, ... do some calculations, return result
})
Here is what i've come up with...
each bot subsribes for market updates,
when market is updated, bot starts computing,
when its finished its emiting completion event,
if its getting termination event from supervisor its stoping computation, if its getting another market update its terminating current execution and starts over...
supervisor subsribes for market updates too,
when its getting one its expecting all bots computation results (no result is also a result :),
if some bot is taking too long its ingnoring him by sending termination event (and counts that bot as returning no result),
as soon as it gets all the bots results its aware of it starts comparing them and emitting the final value to its subscriber,
if it gets another market update while executing it will terminate its computation and start over (waiting for bots)...
Regarding implementation, Bot will manage to handle proper concurrent access to its methods like (start, terminate), as well as Supervisor, eventually those objects ensure no unsafe operation can be done with the object by concurrent execution, using traditional synchronization, but main flow of what triggers what and what happens around is controlled by Rx...
Note that timeout is controlled by supervisor in this case...
Do i miss something here? maybe i'm doing something wrong if i have to use traditional synchronization in conjunction with rx?

Resources