foldright / cffu

🦝 Java CompletableFuture-Fu(CF-Fu, pronounced "Shifu"), a tiny sidekick library to make CompletableFuture usage more convenient, more efficient and safer in your application. 😋🚀🦺
https://github.com/foldright/cffu
Apache License 2.0
172 stars 23 forks source link

report the swallowed exceptions by `M*` methods #263

Open oldratlee opened 1 week ago

oldratlee commented 1 week ago

Errors should never pass silently. Unless explicitly silenced. - https://peps.python.org/pep-0020/

report the swallowed exceptions by M*(including thenM*/MTuple*) methods:

Problem Description

about these M* methods:

so may swallow uncaught exceptions silently.

about peek* methods

peek* methods of cffu have reported uncaught exception of input actions, so the uncaught exceptions will be not swallowed.

https://github.com/foldright/cffu/blob/219007b575396b2412f94a3e13bd2e2dbdbd85eb/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java#L3322-L3334

Implementation Note

handle the CompletableFuture wrappers of actions in order to report the swallowed exceptions.

do NOT report the exceptions that returned to caller, aka. non-swallowed exceptions. repetitive report of exceptions is redundant and unnecessary.

different concurrency strategies are different on exception report:

linzee1 commented 5 days ago

Many libraries offer methods that accept Future parameters. When a Runnable or Callable throws an exception, the error is typically wrapped within a Future (such as CompletableFuture or ListenableFuture in Guava). Methods like mSupplyFailFastAsync only capture the first fail-fast exception, which means other possible exceptions might be ignored. This can lead to poor error handling since it's undesirable to overlook exceptions.

Currently, users must either handle exceptions themselves using try-catch blocks or rely on utility methods that return multiple values—such as a Tuple (e.g., CompletableFuture<List<T>>, List<CompletableFuture<T>>) or a custom class providing methods to process exceptions.

For example:

In the second approach, it might be more efficient to pass the futures directly as parameters. Regardless, we should explicitly document that exceptions could be ignored if not handled properly.

PS: Scala well-known library Cats supports fail-fast operation to enhance for-comprehension with Future. It may also ignore exceptions. Guava methods like whenAllSucceed return FutureCombiner, which handles cancellation propagation and callbacks. It does not need to handle possible exceptions becase of the Future parameters.