user3644708
user3644708

Reputation: 2495

Rest method need long time

This is a design question and I am asking for some ideas. I have a rest method and it will trigger long-time tasks (10~15 minutes) As the function takes long time, I run it as a thread, this can avoid method timeout, but how can I know if the thread went wrong?

Runnable loader = new Runnable() {
        public void run() {
            //tasks
        }
    };

 (new Thread(loader)).start();

Update: the rest service like this

@path()
beginload(){
     //let thread run and return info first
     //how can i know if this thread went wrong?
     (new Thread(loader)).start();
     return "need 15 minutes";        
}

Upvotes: 1

Views: 162

Answers (3)

user41871
user41871

Reputation:

Conceptually there has to be a way for the service to communicate a failure to the client. There are multiple ways you can do this. Here are three examples:

  1. After the client calls the service, the service immediately returns a job ID. The client can use the job ID later to query the service for the status (including error). For example, when you launch instances at AWS EC2, it takes a while for EC2 to service the request, so the launch request returns a so-called "reservation ID" that you can use in subsequent operations (like querying for status, terminating the launch, etc.).
    • Pro: Usable in a wide variety of cases, and easy enough to implement.
    • Con: Requires polling. (I.e. more chatty.)
  2. The client offers a callback URI that the service invokes upon job completion. The callback URI can either be configured into the service, or else passed along as a request parameter. (Don't hardcode the callback URI in the service since services shouldn't depend on their clients.)
    • Pro: Still pretty simple, and avoids polling.
    • Con: Client has to have URI for the service to call, which may not be convenient. (E.g. the client may be a desktop app rather than a service, firewall may prevent it, etc.)
  3. The client pushes a notification into a message queue, and the client listens to that queue.
    • Pro: Avoids polling, and client doesn't need endpoints to call.
    • Con: More work to set up (requires messaging infrastructure).

There are other possibilities but those are typical approaches.

Upvotes: 3

Paul Vargas
Paul Vargas

Reputation: 42020

Do you need to differentiate between different requests? If several tasks to perform, you need an ID.

You can do something like the following:

private static final ExecutorService es = Executors.newFixedThreadPool(10);
private static final Map<Long, Future<Void>> map = new HashMap<>();

@GET
@Path("/submit")
public Response submitTask() {
    long id = System.currentTimeMillis();
    Future<Void> future = es.submit(new Callable<Void>() {
        public Void call() throws Exception {
            // long task
            // you must throw exception for bad task
            return null;
        }
    });
    map.put(id, future);
    return Response.ok(id, MediaType.TEXT_PLAIN).build();
}

@GET
@Path("/status/{id}")
public Response submitTask(@PathParam("id") long id) {
    Future<Void> future = map.get(id);
    if (future.isDone()) {
        try {
            future.get();
            return Response.ok("Successful!", MediaType.TEXT_PLAIN).build();
        } catch (InterruptedException | ExecutionException e) {
            // log
            return Response.ok("Bad task!", MediaType.TEXT_PLAIN).build();
        }
    }
    return Response.ok("Wait a few seconds.", MediaType.TEXT_PLAIN).build();

}

This can give you an idea. Remember purge the map of old tasks.

Upvotes: 2

Paul Lo
Paul Lo

Reputation: 6138

If you want to get the return value of your thread and throw/catch possible exception, consider use Callable rather than Runnable, and it can be used along with ExecutorService which provide more functionality.

Callable : A task that returns a result and may throw an exception.
Implementors define a single method with no arguments called call.

public interface Callable<V> {
    V call() throws Exception;
}

Upvotes: 1

Related Questions