Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interrupt HTTP request after a given number of seconds

Tags:

java

swagger

Im using Java 1.8, dropwizard 1.3.5, and swagger inflection 1.0.13 for my API.

I have a method which takes an HTTP Request, delays 20 seconds, then returns a 200 status code response:

public ResponseContext delayBy20Seconds(RequestContext context) {
    ResponseContext response = new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);

    Thread.sleep(20000);

    response.status(Response.Status.OK);
    return response;
}

Say I want to return a 400 status code if the operation (which in this case takes 20 seconds), takes more than 15 seconds. How would I achieve this?

like image 259
Mark Avatar asked Jan 26 '23 11:01

Mark


1 Answers

One way to do it without additional libraries is by using the java.util.concurrent package. The surest way to cancel a long-running task like this is by running it in a separate thread.

import java.util.concurrent.*;

...

private ExecutorService exec = Executors.newSingleThreadExecutor();
public ResponseContext delayBy20Seconds(RequestContext context) {
    Callable<ResponseContext> task = new Callable<ResponseContext>() {
        @Override
        public ResponseContext call() throws Exception {
            Thread.sleep(20000);
            return new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);
        }
    };
    List<Callable<ResponseContext>> tasks = new ArrayList<>();
    tasks.add(task);
    List<Future<ResponseContext>> done = exec.invokeAll(tasks, 15, TimeUnit.SECONDS);
    Future<ResponseContext> task1 = done.get(0);
    if (task1.isCancelled()) {
        return some Error Response;
    }
    return task1.get();
}

Your ExecutorService should not be static, because you don't want to share it between threads for this particular use.

The Callable<ResponseContext> implementation is where the work for the long-running task is done. And as it should be obvious in the exec.invokeAll call we tell it how much we're willing to wait. The list of Futures returned will always contain as many elements as the list of tasks, so there's no need to check it for emptiness. We just have to check if the task completed or not.

like image 110
coladict Avatar answered Jan 29 '23 13:01

coladict