Auto-complete a Single created from another Observable - rx-java2

I have a long-running operation that returns a value in code I don't control. I need that value to be published to things that ask for it. For this purpose I am using a BehaviorSubject:
var subject: Subject<Value>? = null
fun retrieveValue(): Single<Value> {
if (subject == null) {
subject = BehaviorSubject.create<Value>()
someOtherThing.retrieveValueAsync { value ->
subject.onNext(value)
}
}
return subject.singleOrError()
}
This lets me perform the operation only once and send the result as a single to all future interested parties. However, it does not work. The single will not emit a value until I call:
subject.onComplete()
But this is a problem because once the subject is completed future things can no longer subscribe to it.
What is the appropriate way to cache a value from another observable and pass it to a Single? If there was a way to have a subject automatically complete once its source observable emitted a value that would work. Single.cache() also looks promising, but I'm unsure how I would handle the fact that my value comes in asynchronously in that case.
It feels like I'm missing something silly.

There is a SingleSubject for this case.
If you don't want experimental code in your codebase, you can use ReplaySubject.createWithSize(1) and call onComplete without losing the last value, then convert it to Single.

Related

empty in Monix Task

Project Reactor has something like Mono.empty[T]() which can be handled in special circumstances where you do not have anything when it is evaluated. Is there something similar in Monix Task?
def getItemFromList[T](inp: Mono[List[T]]): Mono[T] = {
val moList = inp.defaultIfEmpty(List[T]())
moList.flatMap[T]((list: List[T]) => {
if (list.isEmpty) Mono.empty[T]()
else Mono.just(list.head)
})
}
Here I am trying to lift an item from a list of items, where the list can be non existent while reading from the db. I do not want to send something like Mono.just(List()) as that will require me to add another empty/null check on the db call side.
Monix' Task and Project Reactor's Mono differ in terms of logic.
While Mono can complete to "nothing", Task can only complete to "something" or never complete at all (which makes a lot more sense).
To correctly describe your problem with Task, you will have to use something like Task[Option[T]] and then return Task.now(None) or move over to Monix' Observable, which models a stream of elements (that can also be empty).

Confused about Observable vs. Single in functions like readCharacteristic()

In the RxJava2 version of RxAndroidBle, the functions readCharacteristic() and writeCharacteristic() return Single<byte[]>.
The example code to read a characteristic is:
device.establishConnection(false).flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(characteristicUUID))
But the documentation for flatMap() says the mapping function is supposed to return an ObservableSource. Here, it returns a Single. How can this work?
Update: I looked at possibilities using operators like .single() and .singleOrError() but they all seem to require that the upstream emits one item and then completes. But establishConnection() doesn't ever complete. (This is one reason I suggested that perhaps establishConnection() should be reimagined as a Maybe, and some other way be provided to disconnect rather than just unsubscribing.)
You're totally correct, this example cannot be compiled. it's probably leftover from RxJava1 version, where Single wasn't exists.
Simple fix with the same result is to use RxJava2 flatMapSingle for instance:
device.establishConnection(false)
.flatMapSingle(rxBleConnection -> rxBleConnection.readCharacteristic(characteristicUUID))
flatMapSingle accepts a Single as the return value, and will map the success value of the input Single to an emission from the upstream Observable.
The point is, that RxJava has more specific Observable types, that exposes the possible series of emission expected from this Observable. Some methods now return Single as this is the logical operation of their stream (readCharacteristic()), some Observable as they will emit more than single emission (establishConnection() - connection status that can be changed over time).
But RxJava2 also provided many operators to convert between the different types and it really depends on your needs and scenario.
Thanks Rob!
In fact, the README was deprecated and required some pimping here and there. Please have a look if it's ok now.
I think I found the answer I was looking for. The crucial point:
Single.fromObservable(observableSource) doesn't do anything until it receives the second item from observableSource! Assuming that the first item it receives is a valid emission, then if the second item is:
onComplete(), it passes the first item to onSuccess();
onNext(), it signals IndexOutOfBoundsException since a Single can't emit more than one item;
onError(), it presumably forwards the error downstream.
Now, device.establishConnection() is a 1-item, non-completing Observable. The RxBleConnecton it emits is flatMapped to a Single with readCharacteristic(). But (another gotcha), flatMapSingle subscribes to these Singles and combines them into an Observable, which doesn't complete until the source establishConnection() does. But the source doesn't ever complete! Therefore the Single we're trying to create won't emit anything, since it doesn't receive that necessary second item.
The solution is to force the generation of onComplete() after the first (and only) item, which can be done with take(1). This will satisfy the Single we're creating, and cause it to emit the Characteristic value we're interested in. Hope that's clear.
The code:
Single<byte[]> readCharacteristicSingle( RxBleDevice device, UUID characteristicUUID ) {
return Single.fromObservable(
device.establishConnection( false )
.flatMapSingle( connection -> connection.readCharacteristic( characteristicUUID ) )
.take( 1L ) // make flatMapSingle's output Observable complete after the first emission
// (this makes the Single call onSuccess())
);
}

Flatmap my observable to subject

The question is a little tricky.
I am trying to implement the observable interface, within it i need to start listen to another publicsubject once the observable meet some circustance, so i write some code like this:
public myAPI(){
return restAPI.call()
.flatmap{ ret ->
if(ret == success) return myPublishSubject
}
can it guarantee the subscribe start subscribe to the publishsubject only after restAPI call is done successfully ?
The flatMap's Function callback is invoked when there is a value from upstream, in this case, the restAPI.call().
However, note that mapping to a PublishSubject late can result in items being missed. To avoid such problems, you can consider using BehaviorSubject that retains the last item it received so the flatMap can emit immediately upon subscribing to it.
In addition, repeatedly mapping to the same Subject can result in memory leaks and item duplication. Unfortunately, you'd have to complete the Subject in order to release it, but then it becomes unusable for dispatching further events. takeUntil may help in this case though.

How to write a function that can be executed in LinqToEntities without loading the object

I have a design problem, but don't know how to fix it. I have a Policy object, with a boolean property like so:
public bool IsCancelled
{
get
{
return (CancellationDate != null && Convert.ToDateTime(CancellationDate) < DateTime.Today);
}
}
The problem with this approach is that if I want to get...
context.Policies.where(q => q.IsCancelled)
...LinqToEntities can't execute this against the database; I must load every policy object into memory, like this statement below, which kills performance and is completely unnecessary:
context.policies.ToList().where(q => q.IsCancelled)
A colleague tells me I should be able to use a Func or Expression to do this, but I'm at a loss as to what phrase to even Google for this. Can someone recommend a link or two that explains how to do this?
Keep in mind, I want this to be available to queries like the one above, and to an instance of a Policy object in memory, without having to code the logic twice (DRY and all that).
Thanks.
The problem is your Convert method. I assume CancelationDate is a string. The real problem here is that SQL doesn't do date comparisons as strings, they need to be in date format. This can't be translated to SQL, and thus won't work in the database.
You really should be storing dates as the date type, not as strings. Then it would be trivial. If you can change this, then do it, then no conversion is necessary.
Your other option is to futz with the EntityFunctions, SqlFunctions, DbFunctions to try to make it work.
See:
Comparing date with string Entity Framework

Can an Rx Observable gracefully handle exceptions in an operator and continue?

i.e., by passing the error condition and not halting the entire Observable?
My Observable starts with a user-supplied list of package tracking numbers from common delivery services (FedEx, UPS, DHL, etc), looks up the expected delivery date online, then returns those dates in terms of number of days from today (i.e. "in 3 days" rather than "Jan 22"). The problem is that if any individual lookup results in an exception, the entire stream halts, and the rest of the codes won't be looked up. There's no ability to gracefully handle, say, UnknownTrackingCode Exception, and so the Observable can't guarantee that it will look up all the codes the user submitted.
public void getDaysTillDelivery(List<String> tracking_code_list) {
Observable o = Observable.from(tracking_code_list)
// LookupDeliveryDate performs network calls to UPS, FedEx, USPS web sites or APIs
// it might throw: UnknownTrackingCode Exception, NoResponse Exception, LostPackage Exception
.map(tracking_code -> LookupDeliveryDate(tracking_code))
.map(delivery_date -> CalculateDaysFromToday(delivery_date));
o.subscribe(mySubscriber); // will handle onNext, onError, onComplete
}
Halting the Observable stream as a result of one error is by design:
http://reactivex.io/documentation/operators/catch.html
Handling Exceptions in Reactive Extensions without stopping sequence
https://groups.google.com/forum/#!topic/rxjava/trm2n6S4FSc
The default behavior can be overcome, but only by eliminating many of the benefits of Rx in the first place:
I can wrap LookupDeliveryDate so it returns Dates in place of Exceptions (such as 1899-12-31 for UnknownTrackingCode Exception) but this prevents "loosely coupled code", because CalculateDaysFromToday would need to handle these special cases
I can surround each anonymous function with try/catch and blocks, but this essentially prevents me from using lambdas
I can use if/thens to direct the code path, but this will likely require maintaining some state and eliminating deterministic evaluation
Error handling of each step, obviously, prevents consolidating all error handling in the Subscriber
Writing my own error-handling operator is possible, but thinly documented
Is there a better way to handle this?
What exactly do you want to happen if there is an error? Do you just want to throw that entry away or do you want something downstream to do something with it?
If you want something downstream to take some action, then you are really turning the error into data (sort of like your example of returning a sentinel value of 1899-12-31 to represent the error). This strategy by definition means that everything downstream needs to understand that the data stream may contain errors instead of data and they must be modified to deal with it.
But rather than yielding a magic value, you can turn your Observable stream into a stream of Either values. Either the value is a date, or it is an error. Everything downstream receives this Either object and can ask it if it has a value or an error. If it has a value, they can produce a new Either object with the result of their calculation. If it has an error and they cannot do anything with it, they can yield an error Either themselves.
I don't know Java syntax, but this is what it might look like in c#:
Observable.From(tracking_code_list)
.Select(t =>
{
try { return Either.From(LookupDeliveryDate(t)); }
catch (Exception e)
{
return Either.FromError<Date>(e);
}
})
.Select(dateEither =>
{
return dateEither.HasValue ?
Either.From(CalculateDaysFromToday(dateEither.Value)) :
Either.FromError<int>(dateEither.Error);
})
.Subscribe(value =>
{
if (value.HasValue) mySubscriber.OnValue(value.Value);
else mySubscribe.OnError(value.Error);
});
Your other option is the "handle"/suppress the error when it occurs. This may be sufficient depending on your needs. In this case, just have LookupDeliveryDate return magic dates instead of exceptions and then add a .filter to filter out the magic dates before they get to CalculateDaysFromToay.