Search code examples
javamultithreadingrestsocketsspring-websocket

Is there a way to allow only one request to be executed at a time in java rest service based on the priority of the request?


I have a Java service with REST API. From the client side there can be multiple request sent at a time, and I want one request to be implemented at a time on server side by the API. The problem is that I need to prioritize the request on the server side. On other words, if there are 10 request sent at a time, I need to set priority on all 10 request at a time using a priority queue, and based on priority one request would be selected. The request can be sent from the same client or multiple clients.

@POST
@Path("/execute")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response execute(String body){
    /// 
    do_something();
}

private void do_something(){
    /// method body
}

Now, in the above code this do_something() can be executed for one request at a time.

Is there any solution for that? I have seen some multi-threading solutions, but none of them are helpful as my requirement is to assign priority to the requests.


Solution

  • So what about using Async REST API?

    • When a call arrives, put the body and the async response in a Priority Queue
    • Have a single background thread polling from the Queue to execute do_something
    • Once do_something is finished, complete the response

    Like this:

    private PriorityBlockingQueue<Pair<String, AsyncResponse>> queue =
           new PriorityBlockingQueue(size, comparator);
    
    @POST
    @Path("/execute")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void run(String body, @Suspended AsyncResponse response){
        /// 
        queue.offer(Pair.of(body, response));
    }
    
    private void do_something(){
        /// method body
    }
    
    // background thread...
    {
       new Thread(() -> {
         while(true) {
           Pair<String, AsyncResponse> p = queue.take();
           Response r = do_something(p.left());
           p.right().resume(r);
         }
       }).start();
    }
    

    The comparator needs to be able to compare the Pair object based on the priorities of the request bodies. Or you can create your own class that implements Comparable.