what happen if a flux/mono/Observable never be subscribed - rx-java2

public void test(){
Mono<String> mono = Mono.just("aaa")
FLux<String> flux = Flux.fromArray()
Observable<String> observable = Observable.from(...)
}
what happened test method has been executed?
all the three object will be collected by GC?
if there's some operation, the operation will never be executed?
if the question above is no, what would happened?

To better understand how Flux and Mono is working, you can imagine them as pipes. When you write code - you are not doing operations on your data, but you only describe what should happen to data when pipe will be complete. To make the pipe complete - you need to subscribe to it (that's the end of the pipe).
For example this code:
Mono sampleMono = Mono.just(1)
.map(Integer::toString)
.doOnNext(System.out::println)
In this code, you only tell, what should be done when someone subscribe to sampleMono. when someone do that - then 1 will be emitted, mapped to String and printed to console. But it will happen only after subscribe.
It's something like water pipeline - you can get cold water from well and install water heater. But you newer get warm water until you use shower or sink (you need to subscribe for warm water :) ).
Mono and Flux are lazy - so it will emit only when someone subscribe. Of course - all of the code lines were executed, but they are responsible for creating "pipeline", and until you subscribe - they remain unused. But maybe java with optimizers will do the thing, and these lines will be removed from machine code at all.

Related

second merged branch ignored in XStreams

I'm working on a Cycle JS app using storage and state plugins.
The app use xstream as reactive library.
I'm incapped in a strange behaviour.
My streams are as this diagram
On first session var update I got this debug result:
debug 0
debug 1
debug 3
PROBLEM: "Debug 2" branch is not executed
If I update the session item (so to produce a new storage event) the two branch ar all executed as expected
debug 0
debug 1
debug 2
debug 3
The same good behavior happen happen if add .remember() at "debug 0"
debug 0
debug 1
debug 2
debug 3
Even stranger, the flow work as expected if I remove filter
Without Filter (and without remember) the flow give this result since the first event
debug 0
debug 1
debug 2
debug 3
My suspect is something observe at "debug 0" before the second branch is attached and so the first event is already consumed.
But how can this happen if the two branch are xs.merged together? How can one branch be executed and second not? The two branch dosen't got filters or other processing, they mererly mapTo a reducer function.
Any suggestion on how to debug and resolve this situations?
The problem happens because storage.session.getItem emits as soon as it's subscribed, and merge(a$, b$) subscribes to a$ before it subscribes to b$, so a$ gets the event, but by the time b$ is subscribed, it has arrived too late. This problem is well known and is called a glitch (in reactive programming), and usually occurs when there is a diamond shaped stream graph, which is exactly your case.
I have two blog posts about glitches which can give you more context: Primer on RxJS schedulers and Rx glitches aren't actually a problem. It mentions RxJS, but xstream is quite close to RxJS in terms of implementation. The difference between xstream and RxJS is that xstream streams are always multicast ("shared"), and RxJS has many scheduler types, but xstream has only one. The default scheduler in RxJS is the same behavior as xstream has.
The solution is to apply .remember() before reaching the diamond. This is because the value being emitted needs to be cached for other consumers of that stream. .remember() simply converts the Stream to a MemoryStream. I think the source stream was initially a MemoryStream, and mapping a MemoryStream creates other MemoryStreams, but filter is an operator that breaks that. filter always returns a Stream, and the reason for this is that MemoryStreams should always have a current value, but filter can remove values, so it's possible that a filtered stream would not have any current value.
As the author of Cycle.js I believe the way cyclejs/storage is designed is not the best, and I think we will find ways of designing these APIs so that confusion with MemoryStream versus Stream is minimized. But for the time being, it's important to understand the difference between these two and plan your app so to avoid diamonds (and glitches), or to use .remember() in the right spots.

flatMap() vs subscribe() in Spring webflux

I am a newbie to Spring WebFlux and trying to convert my spring MVC application to webflux. I return a Mono mono from my service :
List<Store> stores = new ArrayList();
When I do:
mono.subscribe(stores::addAll);
dataexchange.put("stores", stores);
return Mono.just(dataexchange);
Then stores is populated as empty list in response. However, I can verify that subscribe() is working after returning response.
When I do :
return mono.flatmap( (response) -> {
dataexchange.put("stores", response));
return Mono.just(dataexchange);
});
Then stores is populated in the response.
Can someone please explain me what is the difference between the two? Is flatMap blocking?
Thanks in advance !
mono.subscribe(stores::addAll);
is asynchronous. That means, you tell the mono that it can now start evaluating.
What you do is continue processing stores right away - with a huge chance that the Mono hasn't evaluated yet.
So, how can you fix this?
You can block until the Mono has completed:
mono.doOnNext(stores::addAll).block()
Of course, this defeats the purpose of reactive programming. You are blocking the main thread until an action completes, which can be achieved without Reactor in a much simpler fashion.
The right way is to change the rest of your code to be reactive too, from head to toe. This is similar to your second example, where your call to dataexchange is part of the Mono, thus being evaluated asynchronously, too.
The important lesson to be learned is that operations like map or flatMap are not operating on the result of the Mono, but create a new Mono that adds another transformation to the execution of the original Mono. As long as the Mono doesn't evaluate, the flatMap or map operations are not actually doing anything.
I hope this helps.

ReactiveX Retry with Multiple Consumers

Quick question, because I feel like I must be missing something.
I'm using rxjs here because it's what I've got in-front of me, this is a general reactiveX question, I believe.
Let's say I have a set of Observables like so:
network_request = some_thing // An observable that produces the result of a network call
event_stream = network_request.flatMapLatest(function(v) {
return connectToThing(v) // This is another observable that needs v
}) // This uses the result of the network call to form a long-term event-based connection
So, this works ok.
Problem, though.
Sometimes the connection thing fails.
So, if I do event_stream.retry() it works great. When it fails, it redoes the network call and gets a new v to use to make a new connection.
Problem
What happens if I want two things chained off of my network_request?
Maybe I want the UI to do something every time the network call completes, like show something about v in the UI?
I can do:
shared = network_request.share() // Other implementations call this refCount
event_stream = shared.flatMapLatest(...) // same as above
ui_stream = shared.flatMapLatest(...) // Other transformation on network response
If I didn't do share then it would have made two requests, which isn't what I want, but with share, when event_stream later has an error, it doesn't retry the network request because the refcount is still at 1 (due to ui_stream), so it immediately returns completed.
What I want
This is obviously a small example I've made up to explain my confusion.
What I want is that every time the result of event_stream (that long term connection) has an error all of the following happens:
the network request is made again
the new response of that request is used to build a new connection and event_stream goes on with new events like nothing happened
that same response is also emitted in ui_stream to lead to further processing
This doesn't feel like a complicated thing, so I must just be misunderstanding something fundamental when it comes to splitting / fanning out RX things.
Workarounds I think I could do but would like to avoid
I'm looking to export these observables, so I can't just build them again and then say "Hey, here's the new thing". I want event_stream and all the downstream processing to not know there's been a disconnection.
Same for ui_stream. It just got a new value.
I could probably work something out using a Subject as a generation counter that I ping every time I want everything to restart, and put the network_request into a flatMap based on that, so that I can break the share...
But that feels like a really hacky solution, so I feel there has to be a better way than that.
What have I fundamentally misunderstood?
As I've been thinking about this more I've come to the same realization as ionoy, which is that retry just disconnects and reconnects, and upstream doesn't know it was due to an error.
When I thought about what I wanted, I realized I really wanted something like a chain, and also a spectator, so I've got this for now:
network_request = some_thing
network_shadow = new Rx.Subject()
event_stream = network_request.do(network_shadow).flatMapLatest(...)
ui_stream = network_shadow.whatever
This has the property where an retry in event_stream or downstream will cause the whole thing to restart, whereas ui_stream is its own thing.
Any errors over there don't do anything, since network_shadow isn't actually a subscriber to event_stream, but it does peel the values off so long as the main event chain is running.
I feel like this isn't ideal, but it is better than what I was concerned I would have to do, which is have a restartEverything.onNext() in an doOnError, which would have been gross.
I'm going to work with this for now, and we'll see where it bites me...
You need to make your cold observable hot by using Publish. Read http://www.introtorx.com/Content/v1.0.10621.0/14_HotAndColdObservables.html#HotAndCold for a great explanation.

Reactive observable that captures onrendered state changes (in scalajs / js)

I am working with a library (ScalaJS and react specifically) where I have an interesting situation that I assume is pretty routine for an experienced reactive-programmer. I have a Component with State and a callback shouldComponentUpdate(State). The basic idea here is that certainly if the callback is triggered but the State has not changed from the last render, returnfalse. Otherwise, perhaps return true if the State change matters.
I am using a library monix but it seems identical to other reactive libraries so I would imagine this is a fairly context-independent question.
I would like to do something like: have some state that reflects the deltas of State since the last render. On each render, clear the buffer. Or, have a renderedState subject that reflects all rendered states as a sequence, a receivedState subject that reflects all received State updates, and a needsUpdate subject that reflects whether the latest receivedState matches the latest renderedState. I am having trouble actually executing these ideas, though. Here is where I am stuck at:
Here is what I've done for other callbacks:
lazy val channel_componentWillUpdate = channel_create[ComponentWillUpdate[Props, State, ResponsiveLayoutContainerBackend, TopNode]]
def componentWillUpdate(cwupd: ComponentWillUpdate[Props, State, ResponsiveLayoutContainerBackend, TopNode]) =
Callback {
channel_componentWillUpdate.onNext(cwupd)
}
So when then componentWillUpdate callback is triggered, the handler fires onNext on the channel (subject).
The shouldComponentUpdate is different though. It returns a value, so it needs to be structured differently. I am having trouble thinking of the right adjustment.
To summarize a bit:
react has callbacks at different stages of the view lifecycle, like componentDidMount, componentDidUpdate, etc.
I am handling all but one stage the same way - the shape of the callback is State -> Callback<Void> so alls I have to do is use a Subject for each type of lifecycle event and submit its onNext when the callback is triggered.
But one type of event has shape either State -> Boolean or State -> Callback<Boolean>.
I feel like I should be able to model this with a subject representing the delta between the last state rendered/received.
However, I don't know how this fits into the reactive style.

What do the various ISubject implementations do and when would they be used?

I have a fairly good idea of what the Subject class does and when to use it, but I've just been looking through the language reference on msdn and see there are various other ISubject implementations such as:
AsyncSubject
BehaviorSubject
ReplaySubject
As the documentation is pretty thin on the ground, whats the point of each of these types and under what situations would you use them?
These subjects all share a common property - they take some (or all) of what gets posted to them via OnNext and record it and play it back to you - i.e. they take a Hot Observable and make it Cold. This means, that if you Subscribe to any of these more than once (i.e. Subscribe => Unsubscribe => Subscribe again), you'll see at least one of the same value again.
ReplaySubject: Every time you subscribe to the Subject, you get the entire history of what has been posted replayed back to you, as fast as possible (or a subset, like the last n items)
AsyncSubject: Always plays back the last item posted and completes, but only after the source has completed. This Subject is awesome for async functions, since you can write them without worrying about race conditions: even if someone Subscribes after the async method completes, they get the result.
BehaviorSubject: Kind of like ReplaySubject but with a buffer of one, so you always get the last thing that was posted. You also can provide an initial value. Always provides one item instantly on Subscribe.
In light of the latest version (v1.0.2856.0) and to keep this question up to date, there has been a new set of subject classes:
FastSubject, FastBehaviorSubject, FastAsyncSubject and FastReplaySubject
As per the release notes they
are much faster than regular subjects
but:
don’t decouple producer and consumer by an IScheduler
(effectively limiting them to
ImmediateScheduler);
don’t protect against stack overflow;
don’t synchronize input messages.
Fast subjects are used by Publish and
Prune operators if no scheduler is
specified.
In regards to AsyncSubject
This code:
var s = new AsyncSubject<int>();
s.OnNext(1);
s.Subscribe(Console.WriteLine);
s.OnNext(2);
s.OnNext(3);
s.OnCompleted();
prints a single value 3. And it prints same if subscription is moved to after completion. So it plays back not the first, but the last item, plays it after completion (until complete, it does not produce values), and it does not work like Subject before completion.
See this Prune discussion for more info (AsyncSubject is basically the same as Prune)
Paul's answer pretty much nails it. There's a few things worth adding, though:
AsyncSubject works as Paul says, but only after the source completes. Before that, it works like Subject (where "live" values are received by subscribers)
AsyncSubject has changed since I last ran tests against it. It no longer acts as a live subject before completion, but waits for completion before it emits a value. And, as Sergey mentions, it returns the last value, not the first (though I should have caught that as that's always been the case)
AsyncSubject is used by Prune, FromAsyncPattern, ToAsync and probably a few others
BehaviorSubject is used by overloads of Publish that accept an initial value
ReplaySubject is used by Replay
NOTE: All operator references above refer to the publishing set of operators as they were before they were replaced with generalised publish operators in rev 2838 (Christmas '10) as it has been mentioned that the original operators will be re-added