question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[PIP-149] Making the REST Admin API fully async

See original GitHub issue

Co-author: @mattisonchao @Technoboy-

Motivation

The Rest API was originally designed to be implemented asynchronously, but with the iteration of functions, some synchronous implementations were added, resulting in many asynchronous methods called synchronous implementations. Also, many synchronous calls do not add timeouts. This greatly reduces concurrency, user operations, and experience. In order to prevent more problems, and improve code readability and maintainability, we intend to refactor these synchronous calls and standardize the implementation of the API.

Related discussion: https://lists.apache.org/thread/pkkz2jgwtzpksp6d4rdm1pyxzb3z6vmg

Goals

  • Try to avoid synchronous method calls in asynchronous methods.
  • Async variable (AsyncResponse) is placed in the first parameter position.
  • Async variable (AsyncResponse) cannot be substituted into method implementations.
  • Add more tests and increase the coverage.

Modification

  1. Avoid synchronous method calls in asynchronous methods.

    protected void internalDeleteNamespace(boolean authoritative) {
       validateTenantOperation(namespaceName.getTenant(), TenantOperation.DELETE_NAMESPACE);
       validatePoliciesReadOnlyAccess();
    }
    

    Suggest to do like this:

    protected CompletableFuture<Void> internalDeleteNamespace(boolean authoritative) {
        return validateTenantOperationAsync(namespaceName.getTenant(), TenantOperation.DELETE_NAMESPACE)
       .thenCompose(__ -> validatePoliciesReadOnlyAccessAsync());
    }
    
  2. Async variable (AsyncResponse) is placed in the first parameter position

    public void deleteNamespace(@Suspended final AsyncResponse asyncResponse, 
             @PathParam("tenant") String tenant,
             @PathParam("namespace") String namespace,
             @QueryParam("force") @DefaultValue("false") boolean force,
             @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
    
    
  3. Async variable (AsyncResponse) cannot be substituted into method implementations

    internalCreateNonPartitionedTopicAsync(asyncResponse, authoritative, properties);
    

    Suggest to do like this:

    internalCreateNonPartitionedTopicAsync(authoritative, properties)
            .thenAccept(__ -> asyncResponse.resume(Response.noContent().build()))
            .exceptionally(ex -> {
                resumeAsyncResponseExceptionally(asyncResponse, ex.getCause());
                return null;
            });
    
  4. Exception Some methods will validate ownership, like namespace ownership, topic ownership, so will throw REDIRECT exception. we need to filter this exception and not print log.

 internalCreateNonPartitionedTopicAsync(authoritative, properties)
        .thenAccept(__ -> asyncResponse.resume(Response.noContent().build()))
        .exceptionally(ex -> {
            if (!isRedirectException(ex)) {
                 log.error("Failed to xxx");
            }
            resumeAsyncResponseExceptionally(asyncResponse, ex.getCause());
            return null;
        });

Task tracking

In order to unify the modification and track the modified part, it’s better to open an issue to track, like Apache/Pulsar#14353, Apache/Pulsar#14013, Apache/Pulsar#13854.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
lhotaricommented, Feb 18, 2022

@codelipenghui @lhotari @eolivelli @BewareMyPower @nodece @mattisonchao I have opened this issue to discuss first then decide to make to PIP

Thank you @Technoboy- . Good work. I shared my thoughts and some expectations in yesterdays Pulsar Community meeting, you can find the discussion and @merlimat’s responses of the rationale for the changes. It would be good to document the arguments that Matteo explained why mixing async and blocking (sync) causes issues. Please check the last 35 minutes from the recording of the meeting (it’s not available yet, @merlimat could you please add the recording on https://github.com/apache/pulsar/wiki/Community-Meetings#recordings ?) I’ll be able to follow up at the beginning of March the next time. There’s no need to wait for me to reply.

While digging into the Jetty settings in Pulsar, I noticed a few gaps in backpressure handling, which are relevant when there are more requests which are handled asynchronously. I have a draft PR #14353 . I’ll resume work on that in March. The current values for queue sizes and thread pool sizes are just guesses. Most likely we will use much lower values to prevent the broker taking in too much work in parallel. That’s the essence of back pressure that it limits the in progress work so that incoming requests also slow down. Currently that is not the case since the thread pool queue can grow in an unbounded way (LinkedBlockingQueue is used under the covers). There are several kludges that attempt to add backpressure, but they aren’t very effective in Pulsar currently. #14353 will help address backpressure issues in Pulsar Admin API. These problems will come more evident when there are more APIs which are implemented using asynchronous Servlet API. /cc @merlimat @codelipenghui

5reactions
Technoboy-commented, Feb 18, 2022

@codelipenghui @lhotari @eolivelli @BewareMyPower @nodece @mattisonchao I have opened this issue to discuss first then decide to make to PIP

Read more comments on GitHub >

github_iconTop Results From Across the Web

REST Admin API reference - Shopify Developers
The Admin API lets you build apps and integrations that extend and enhance the Shopify admin. Learn how to get started with REST...
Read more >
Asynchronous refresh for Azure Analysis Services models
Describes how to use the Azure Analysis Services REST API to code asynchronous refresh of model data.
Read more >
Interacting asynchronously with REST APIs by using the ... - IBM
You can make REST requests and receive responses asynchronously by using RESTAsyncRequest and RESTAsyncResponse nodes in your message flow.
Read more >
Managing Asynchronous Workflows with a REST API
While building REST APIs, architects often discover that they have ... URL that is called back when the asynchronous operation is complete.
Read more >
REST API - Asynchronous Inbound flow to return sys_id
Hi Everyone, We are using REST API - Asynchronous trigger (post) and created an Inbound flow. The requirement is after the payload from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found