Skip to content

[improve][misc] Return failed future in async method instead of throw exception directly#20521

Open
Shawyeok wants to merge 1 commit intoapache:masterfrom
Shawyeok:return-failed-future-insteadof-throw-exception
Open

[improve][misc] Return failed future in async method instead of throw exception directly#20521
Shawyeok wants to merge 1 commit intoapache:masterfrom
Shawyeok:return-failed-future-insteadof-throw-exception

Conversation

@Shawyeok
Copy link
Copy Markdown
Contributor

@Shawyeok Shawyeok commented Jun 7, 2023

Motivation

Throws an exception from a async method generally a bad practice, for example in ProducerBuilderImpl#createAsync, checkArgument may throws a runtime exception directly:

public CompletableFuture<Producer<T>> createAsync() {
// config validation
checkArgument(!(conf.isBatchingEnabled() && conf.isChunkingEnabled()),
"Batching and chunking of messages can't be enabled together");

If user call it in a async context, it may cause some unexpected behavior, here is a case:

CompletableFuture<xxx> future = new CompletableFuture<>();
xxx.whenComplete((v, ex) -> {
    xxx.createAsync().whenComplete((v, ex) -> {
        if (ex != null) {
            future.completeExceptionally(ex);
        } else {
            future.complete(v);
        }
    });
})

If createAsync() throws an exception from inside, the future will never get completed. This kind of problem is very hard to troubleshooting cause it could haven’t any log.

So I wrote a PMD rule to examine the entire Pulsar codebase (current master branch), aiming to identify similar kinds of problems. Here it is:

//MethodDeclaration[matches(@Name, "Async$")]
  [.//PrimaryPrefix/Name[matches(@Image, "(requireNonNull|checkNotNull|checkState|checkArgument)$")]]

Note: this rule may not be able to scan all similar code issues.

Modifications

Return a failed future instead of throw exception directly, for the given case above, it's will be change to:

public CompletableFuture<Producer<T>> createAsync() {
    // config validation
    if (conf.isBatchingEnabled() && conf.isChunkingEnabled()) {
        return FutureUtil.failedFuture(
                new IllegalArgumentException("Batching and chunking of messages can't be enabled together"));
    }

Verifying this change

  • Make sure that the change passes the CI checks.

Does this pull request potentially affect one of the following parts:

If the box was checked, please highlight the changes

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

Documentation

  • doc
  • doc-required
  • doc-not-needed
  • doc-complete

Matching PR in forked repository

PR in forked repository: Shawyeok#9

@github-actions github-actions Bot added the doc-not-needed Your PR changes do not impact docs label Jun 7, 2023
@lhotari
Copy link
Copy Markdown
Member

lhotari commented Jun 7, 2023

Thanks for the contribution.

This is a breaking change in the API since exceptions could also be considered as part of the API although they aren't explicitly stated in the Java interface files. We use the PIP process to track changes to public APIs in Pulsar.

The other benefit of a PIP is that there will be broader awareness of the change in our approach to handle method parameter validation in asynchronous methods. The PIP process will help ensure better consistently in the project in the future.

@Shawyeok please start a new PIP for this change.

Copy link
Copy Markdown
Member

@lhotari lhotari left a comment

Choose a reason for hiding this comment

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

Blocking the changes since I think that we need a PIP for public API changes. I provided the rational in my previous comment.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jul 8, 2023

The pr had no activity for 30 days, mark with Stale label.

@github-actions github-actions Bot added the Stale label Jul 8, 2023
@Technoboy- Technoboy- added this to the 3.2.0 milestone Jul 31, 2023
@Technoboy- Technoboy- modified the milestones: 3.2.0, 3.3.0 Dec 22, 2023
@coderzc coderzc modified the milestones: 3.3.0, 3.4.0 May 8, 2024
@lhotari lhotari modified the milestones: 4.0.0, 4.1.0 Oct 14, 2024
@coderzc coderzc modified the milestones: 4.1.0, 4.2.0 Sep 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants