Mutiny provides several operators to handle failures.
Remember, failures are terminal events sent by the observed stream, indicating that something bad happened. After a failure, no more items are being received.
When such an event is received, you can:
propagate the failure downstream (default), or
transform the failure into another failure, or
recover from it by switching to another stream, passing a fallback item, or completing, or
retrying (covered in the next guide)
If you don’t handle the failure event, it is propagated downstream until a stage handles the failure or reaches the final subscriber.
It can be useful to execute some custom action when a failure happens. For example, you can log the failure:
Uni<String> u = uni .onFailure().invoke(failure -> log(failure)); Multi<String> m = multi .onFailure().invoke(failure -> log(failure));
You can also execute an asynchronous action using
Another useful action on failure is to transform the failure into a more meaningful failure.
Typically, you can wrap a low-level failure (like an
IOException) into a business failure (
Uni<String> u = uni .onFailure().transform(failure -> new ServiceUnavailableException(failure));
In general, upon failure, you want to recover. The first approach is to recover by replacing the failure with an item:
Uni<String> u1 = uni .onFailure().recoverWithItem("hello"); Uni<String> u2 = uni .onFailure().recoverWithItem(f -> getFallback(f));
The second approach receives a
Supplier to compute the fallback item.
For the downstream, it didn’t fail; it gets the fallback item instead.
However, don’t forget that failures are terminal!
Multi, the downstream receives the fallback item followed by the completion signal, as no more items can be produced.
When observing a
Multi you can replace the failure with the completion signal:
Multi<String> m = multi .onFailure().recoverWithCompletion();
The downstream won’t see the failure, just the completion event.
On failure, you may want to switch to an alternate stream. When the failure is received, it subscribes to this other stream and propagates the items from this stream instead:
Uni<String> u = uni .onFailure().recoverWithUni(f -> getFallbackUni(f)); Multi<String> m = multi .onFailure().recoverWithMulti(f -> getFallbackMulti(f));
recoverWithMulti methods replace the failed upstream with the returned stream.
The fallback streams must produce the same type of event as the original upstream.