Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch generic throwable and pass exception to returned future #1285

Merged
merged 2 commits into from
Oct 14, 2022

Conversation

elefeint
Copy link
Contributor

@elefeint elefeint commented Oct 10, 2022

This PR adds a catch-all for any unforeseen errors and passes the error to the returned future.

In normal code, catching Throwable is a bad idea -- the error should be allowed to propagate and stop the app. However, when running in a separate thread, an uncaught Throwable will simply disappear without a trace, so we have to catch it and hand the error over to the returned future, so that the failure may be acted upon.

Unrelated changes:

  • lightly refactored to have the template get created before each test, since every test will need it.
  • somehow this test was still on JUnit4. Upgraded to JUnit5.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Oct 10, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

@@ -285,6 +285,9 @@ public ListenableFuture<WriteApiResponse> writeJsonStream(
writeApiFutureResponse.setException(e);
// Restore interrupted state in case of an InterruptedException
Thread.currentThread().interrupt();
} catch (Throwable t) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elefeint Catching a wider exception is a good idea here and thanks for making the changes. However shall we catch Exception instead? Catching Throwable results in this Sonar issue: https://sonarcloud.io/project/issues?resolved=false&types=CODE_SMELL&pullRequest=1285&id=GoogleCloudPlatform_spring-cloud-gcp&open=AYPCUFuggImngqXU1xdj

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sonar is right, in general, however the user experience will be significantly worse if we follow this recommendation -- for example, if an unexpected Exception (or even Throwable such as linkage errors) arises during the separate thread execution, the error will just disappear without leaving a trace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That causes 2 issues:

  1. The error disappears without any user-visible evidence.
  2. CompletableFuture will be left hanging forever.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense @elefeint

Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what would be a better way to handle exceptions from the asynchronous task. In this case, catching Throwable or Exception seems appropriate.

@elefeint elefeint merged commit 0e3a7e2 into main Oct 14, 2022
@elefeint elefeint deleted the fix-hanging-future branch October 14, 2022 15:14
kateryna216 added a commit to kateryna216/spring-cloud-gcp that referenced this pull request Oct 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants