Is it possible to merge an Observable to another after a subscription was made, so the Observer can see the result?
I know this doesn't work, but I mean something like this:
observable.subscribe( (i) -> doSomething(i) );
observable.merge(anotherObservable);
And then doSomething will receive the values of anotherObservable as well.
Also, is it there a way to keep merging, even if all merged Observables already completed?
Related
I am searching for a way to repeat the last element when the subscriber of a Flux signals onNext but the publisher did not supply a new element.
Of course this approach would logically introduce eager streaming, but in my case that's exactly what I want, similarly to onBackpressureDrop and others, where an infinite demand is requested upstream.
I kind of need the exact opposite - with my subscriber being faster than the publisher.
I struggle to think of a case where it wouldn't be better for the subscriber to simply cache the last emitted value within itself and do what it needs to do there (whether that's looping, firing on a scheduled executor or something else entirely) rather than deliberately having an infinite demand on the last value emitted by the Flux.
Something akin to the following might work, but is incredibly hacky (that being said, I couldn't think of a better way):
flux.subscribe(str -> {
Mono.just(str).repeat().takeUntilOther(flux.next())
.subscribe(s -> {
//Actual subscriber
});
});
I want to implement the following functions in the most re-active way. I need these for implementing the bijections for automatic conversion between the said types.
def convertScalaRXObservableToTwitterFuture[A](a: Observable[A]): TwitterFuture[A] = ???
def convertScalaRXObservableToTwitterFutureList[A](a: Observable[A]): TwitterFuture[List[A]] = ???
I came across this article on a related subject but I can't get it working.
Unfortunately the claim in that article is not correct and there can't be a true bijection between Observable and anything like Future. The thing is that Observable is more powerful abstraction that can represent things that can't be represented by Future. For example, Observable might actually represent an infinite sequence. For example see Observable.interval. Obviously there is no way to represent something like this with a Future. The Observable.toList call used in that article explicitly mentions that:
Returns a Single that emits a single item, a list composed of all the items emitted by the finite source ObservableSource.
and later it says:
Sources that are infinite and never complete will never emit anything through this operator and an infinite source may lead to a fatal OutOfMemoryError.
Even if you limit yourself to only finite Observables, still Future can't fully express semantics of Observable. Consider Observable.intervalRange that generates a limited range one by one over some time period. With Observable the first event comes after initialDelay and then you get event each period. With Future you can get only one event and it must be only when the sequence is fully generated so Observable is completed. It means that by transforming Observable[A] into Future[List[A]] you immediately break the main benefit of Observable - reactivity: you can't process events one by one, you have to process them all in a single bunch.
To sum up the claim at the first paragraph of the article:
convert between the two, without loosing asynchronous and event-driven nature of them.
is false because conversion Observable[A] -> Future[List[A]] exactly looses the "event-driven nature" of Observable and there is no way to work this around.
P.S. Actually the fact that Future is less powerful than Observable should not be a big surprise. If it was not, why anybody would create Observable in the first place?
Trying to migrate to rx-java2and came across a problem with resubscribing the shared observable inside it's own flatMap. Need this pattern to get-update-refresh chain:
Get current data from network (shared observable to avoid multiple network requests if source is being subscribed by several observers at the same time).
Modify the data and send it back to server (completable)
Get the data again after update completes
The whole thing looks like this:
#Test fun sharedTest() {
val o = Observable.just(1).share()
assertEquals(1, o
.take(1)
.flatMap({
Completable.complete()
.andThen(o) })
.blockingFirst())
}
The test fails with: java.util.NoSuchElementException
If o is not shared everything works.
That behavior seems to be because the latter subscriber comes when a single value of original has already been dispatched and only onComplete event is to be seen.
Does anybody know is that a by-design behavior and documented somehow? There is a workaround of course but I need to know the cause, as this is a bit annoying. The approach worked in Rx 1.x
Currently using version 2.1.3
Edit:
Seems to be no legitimate way to "restart" a shared observable and its side-effects as there is no guarantee other subscribers are not listening at the moment.
Take a look at the bubble diagram for 'share' and you'll see why it behaves like that: Observable.share().
share() emits items that are emitted after the subscription, it does not re-emit previously emitted items. Take a look at Observable.replay() for the behavior that should be what you expect.
Seems to be no legitimate way to "restart" a shared observable and its side-effects as there is no guarantee other subscribers are not listening at the moment.
Is there a way to make an Observable emulate a BehaviorSubject (but without the Observer interface) in rx-scala? I.e. make it an Observable with memory, so that it can have multiple subscriptions, and on each new subscription, it produces the last emitted value?
Observable.publish() does half the job, but it doesn't emit the last value. Observable.cache.publish() on the other hand replays all values - I would need something like that, but which only replays the last emitted value, to handle infinite streams.
Rx-Java solutions also accepted, although the native Scala form is preferred!
How about simply using the existing BehaviorSubject Scala implementation? As you can see, it's certainly available in 0.16.0, and I'm certain 0.15.0 includes it as well.
With the scala bindings, use observable replay 1 refCount.
I am implementing a bus using Rx (reactive framework) and so far it looks good. The problem that I am facing right now is how to add events before the beginning of a stream.
To give more context, this is for an Event Source (a la CQRS/ES). When the bus starts, a number of subscribers get the IObservable. At this point, the bus asks the subscribers what event number/sequence they need to start at. The events are loaded from disk starting at the lowest number and added to the stream, with each subscriber using a where statement to start at the right event. As the application runs, new events get added and go to the subscribers. This part works great.
Some subscribers that attach late, but still need all the events. It looks like ReplaySubject fits the bill, as long as the number of events is small enough. I am thinking that I can probably do some disk/offline caching to keep more them around (any pointers welcome!).
The bigger issue is that when some subscribers get the IObservable, they need to get events that occurred before the ones that were loaded initially. A situation like the following.
When the bus started it loaded event #50 onward (the earliest anyone wanted). Now, a new subscriber requests the IObservable, except they need from #20 onward. So what I want to do is load 20-49, and add them before the start of the stream. None of the existing subscribers should see any of the events (it will be filtered by the Where).
It seems like this should be possible, but I can't quite get my head around it. Is this possible in Rx? If so, how?
Thanks!
Erick
I would look at this in a very simple Rx way. Don't use a ReplaySubject, use a single Subject for all of the "live" events and concat the historical events in front of this for each subscriber.
I would imagine that you might have some sort of data structure that keeps track of the historical records. If you've loaded/captured events from #50 to say #80 in memory already, then when a new subscriber comes along that requests the events from #20 I'd do something like this:
var fromIndex = 20;
var eventSubject = new Subject<Event>();
capturedEvents
.GetFromIndex(fromIndex) // Gets a enumerable list of events
.ToObservable()
.Concat(eventSubject)
.Subscribe( ... );
You then can have the eventSubject be used to capture new events, like so:
eventSubject.Subscribe(capturedEvents.CaptureEvent);
Does this meet your need?
How about just:
itemsFromTwentyToFourtyNine.Concat(currentItems);