Observer<T>.OnError's assumptions seem to be inconsistent with Stubs.Throw - system.reactive

One of the overloads on IObservable<T>.Subscribe is
public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)
Internally, this creates and registers an AnoymousObserver<T> on the IObservable. The unspecified onError parameter is set to Stubs.Throw which is a simple lambda that rethrows the exception passed in.
Internally, the observers for an IObservable are all contained in a single instance of type Observer. This is the code in Observer<T>.OnError
public void OnError(Exception error)
{
foreach (var observer in _observers.Data)
observer.OnError(error);
}
Since Stubs.Throw throws the exception, the exception from that observer's OnError passes up through the foreach loop and other observers in _observers.Data never have their OnError called. The exception itself is swallowed somewhere inside Rx.
It seems to me that either Observer<T>.OnError should wrap observer.OnError in a try-catch, or Stubs.Throw should swallow the exception instead of throwing it. By not passing an onError parameter, the user of IObservable.Subscribe wishes the error to be ignored only for that Subscribe. The other subscribers registered with their own onError callbacks should be unaffected.
(I already filed a bug on Codeplex but the tracker looks deserted, so I thought I'd ask on SO too to see if I'm understanding this correctly.)
Update: Asti's answer is correct. In the discussion on the linked bug report, davedev gave an analogy with IEnumerable, and how the default of throwing the exception unhandled is the equivalent of the default of iterating an IEnumerable without a catch block.
If the observable determines that a particular exception should not be considered fatal, it should not communicate this using OnError. OnError is not guaranteed to be executed since calling it implies something went seriously wrong with the observable in the first place. Instead, the observable can be defined as an IObservable<Either<T, Exception>> (example usage in Observable2.Retry).

This is actually the expected behavior.
OnError is not a method to be called to indicate that an exception was thrown on an observer's OnNext - it is to denote the abnormal termination of an observable sequence. The default OnError implementation will throw the exception as the notification transitions out of the Observable monad.
You will have more clarity on the Rx contract and exception handling if you read the Rx Design Guidelines. As for error handling along the pipeline, and more IEnumerable/IQueryable-like behavior, have a look at SubscribeSafe.

Related

Micrometer timer exception handling

I want to handle exception thrown in method which is recorded. For example, I send message to kafka with method kafka.send(), I record it: timer.record(() -> kafka.send())
Kafka may produce some exception and if its happened, I want to make some kind of transaction and rollback some code. How can I handle exception thrown in kafka.send method? As I saw in code of timer.record, it swallows exception, is it right?
No, timer.record method doesn't swallow the exception. There is only finally-block, but no catch-block: https://github.com/micrometer-metrics/micrometer/blob/main/micrometer-core/src/main/java/io/micrometer/core/instrument/AbstractTimer.java
And you can handle the exception in your code as usual.

The function has return type of 'FutureOr<User>', but doesn't end with a return statement

I am trying to create a repository for use cases of FirebaseAuth and can see warnings!
Should I ignore the warning, as it not impacting the app?
OR should I handle it now, and How?
Dart has analyzed your program and found out that you have not handled all cases how the method can exit. This is a potentially a problem since your method signature specifies that you method are returning a Future<User> object.
In your case you have not handled the case where an exception are throw from the createUserWithEmailAndPassword method. If an exception are catch, you ends up with a execution path without any return statement.
In this case, Dart will at runtime just return null so it is not an error. But it is a potential sign of a code error since it it not unlikely that you have forgotten the handling of the exception by not have any return statement.
If it is your intention to just return null in case of an exception, you should therefore have insert return null; in both of your catch blocks (or just at the bottom of your method outside the catch-blocks).
Alternative, you can rethrow the exception if you just want to add some logging but still let the caller to also handle the exception. You can read more about this in the language tour: https://dart.dev/guides/language/language-tour#catch
In either cases, you should describe the behavior in the documentation of the method.

How to call a method in a catch clause on an object defined in a try clause?

I am creating a redis pubsub client in a try-catch block. In the try block, the client is initialised with a callback to forward messages to a client. If there's a problem sending the message to the client, an exception will be thrown, in which case I need to stop the redis client. Here's the code:
try {
val redisClient = RedisPubSub(
channels = Seq(currentUserId.toString),
patterns = Seq(),
onMessage = (pubSubMessage: PubSubMessage) => {
responseObserver.onValue(pubSubMessage.data)
}
)
}
catch {
case e: RuntimeException =>
// redisClient isn't defined here...
redisClient.unsubscribe(currentUserId.toString)
redisClient.stop()
messageStreamResult.complete(Try(true))
responseObserver.onCompleted()
}
The problem is that the redis client val isn't defined in the catch block because there may have been an exception creating it. I also can't move the try-catch block into the callback because there's no way (that I can find) of referring to the redisClient object from within the callback (this doesn't resolve).
To solve this I'm instantiating redisClient as a var outside the try-catch block. Then inside the try block I stop the client and assign a new redisPubSub (created as above) to the redisClient var. That's an ugly hack which is also error prone (e.g. if there genuinely is a problem creating the second client, the catch block will try to call methods on an erroneous object).
Is there a better way of writing this code so that I can correctly call stop() on the redisClient if an exception is raised when trying to send the message to the responseObserver?
Update
I've just solved this using promises. Is there a simpler way though?
That exception handler is not going to be invoked if there is a problem sending the message. It is for problems in setting up the client. This SO answer talks about handling errors when sending messages.
As for the callback referring to the client, I think you want to register the callback after creating the client rather than trying to pass the callback in when you create it. Here is some sample code from Debashish Ghosh that does this.
Presumably that callback is going to run in another thread, so if it uses redisClient you'll have to be careful about concurrency. Ideally the callback could get to the client object through some argument. If not, then perhaps using volatile would be the easiest way to deal with that, although I suspect you'd eventually get into trouble if multiple callbacks can fail at once. Perhaps use an actor to manage the client connection, as Debashish has done?

How to fix "EntityMemberChanged was called without first calling EntityMemberChanging"

This came up time and again for us. After reading such a message, there's nothing intuitive to do and debug.
What this poorly-documented error is trying to say is that you accidentally set up a system in which tracking changes causes more changes.
When Entity Framework changed a property on one of your entities, such as during SaveChanges with identity ID updates, you ran code that changed other tracked properties.
For example, the property that Entity Framework was setting triggered an event, perhaps INotifyPropertyChanged, which perhaps was subscribed to by a BindingSource or some binding list, whose ListChanged event handler was in the UI and triggered a calculation of some other property, and the change tracker detected the second property change.
The simple diagnosis is to place a breakpoint on the SaveChanges() call and immediately after the SaveChanges call(). When the first breakpoint is hit, place a breakpoint on each event handler that could possibly be triggered. (BindingSources are notorious for multiplying each other's events.) Continue debugging. If any breakpoint is hit other than the point immediately following SaveChanges, you know where the problem is.
The simple solution is to set a flag, such as IsSaving, on each side of the SaveChanges call. Then in each misbehaving event handler, do a simple check and do not modify any entities if the DbContext is in the process of saving. Make sure you use finally in case SaveChanges throws an exception that you catch at a higher level:
IsSaving = true;
try
{
await db.SaveChangesAsync()
}
finally
{
IsSaving = false;
}
(One other possibility is that you were changing the entity from multiple threads — never involve the change tracker in multiple threads!)
I had the exact same issue. I had wired to the INotifyPropertyChanged event that created the possibility for a property to change during the SaveChanges() call. I think it is a better practice to unwire the event handlers of you tracked entities when performing dbContext.SaveChanges(), Remove().
I'll explain my experience with this error, hoping it might help someone. And thanks to jnm2 for beautiful explanation.
I had Invoice and Receipt entities, and InvoiceViewModel.
Thie ViewModel was subscribed to Invoice property changed, inside which it was raising CanExecuteChanged events.
I added Receipt to Invoice navigation property and called SaveChanges(), which raised Invoice.ReceiptID property changed and triggered OnPropertyChanged event handler on the ViewModel, which in turn raised all kinds of CanExecuteChanged events.
The problem was that one of the CanCommandNameExecute methods was calling Context.ChangeTracker.HasChanges() which ultimately threw an exception.
How I fixed it?
I followed jnm2, I flagged VM with IsSaving and checked for the flag inside OnPropertyChanged event handler.
Once again, thanks jnm2, and hope someone finds this helpful as well.

GWT app getting java.util.ConcurrentModificationException from MVC pattern

I am getting this error everytime my Observers are traversed.
#Override
public void notifyObservers(ModelViewInterface model) {
for(Observer<ModelViewInterface> o : this.observers)
o.notify(model);
}
GWT does not have threads, so it is not a synchronization issue.
It seems to happen after I press a button, any ideas of how to avoid this error?
From the javadoc of ConcurrentModificationException:
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
So in your case, it seems that o.notify(model) modifies this.observers - directly or indirectly. This is a common phenomenon when modifying the collection you're iterating over.
To avoid concurrent modification, you can operate on a copy of the collection like this:
for(Observer<ModelViewInterface> o :
new ArrayList<ModelViewInterface>(this.observers)) {
o.notify(model);
}
However, sometimes this is not what you want - the current behaviour of o.notify could also indicate a bug.