简体   繁体   中英

Implement a long-running process in a web app

For some reason I can't find on google a solution for this. I have an option in a web app to upload a large amount of data (in a file) and through back-end processing (we use Java/Spring) to store this. It takes like 5 minutes. Does anybody know of a way that a user can launch this process and do other things and when it's done to inform the user?

A solution that I'm thinking about (not sure if there are better once, that's why I'm here) is to make an AJAX call (we happen to use the jQuery library) which will pass the file to a controller, then while the controller will be processing the file it will periodically send something small to the stream so that timeout doesn't happen and then once it's finished it will inform about that the web app upon which it will inform the user.

I had to solve a problem like this recently and it was really easy. He's why I say so.

  1. With HTTP 1.1 protocol, the server connection is kept open until the last resource for a request is returned. Any HTTP 1.1 compliant web-server will do this for you under the hood without any effort on your part. This alone makes your problem much, much easier to solve

  2. With servlet 3.0, you should take advantage of the new asynchronous feature (although you can roll out something similar on your own in servlet < 3.0). The server allocates a new thread for each incoming request from it's thread pool. Then using your own custom thread-pool, hand off the processing of this request thread to a custom-thread together with the asyncContext. Your own thread will handle this long-running process, and the server's thread returns immediately to process other requests. The asyncContext contains the original request/response objects, but they're in a 'frozen' state. When your long-running process completes, it will invoke the asyncContext.complete() method. This action will commit the original request/response that was in 'frozen' state.

  3. To the client, this asynchronous process looks like the server is taking forever to respond, and the client will therefore sit patiently waiting for a response. You will need to do nothing out of ordinary on your part.

  4. On the client side, any method of invoking an ajax request is sufficient. No polling is required. The client will happily sit and wait for a response. The 'readyState' attribute of the xmlHttpRequest object will take care of this for you. Once the response is committed by the server, the 'readyState' value will change to 4 and from there you can update your UI.

On the server side, you should probably wrap the class having the method to the long-running process inside an inner class which will then invoke the long-running process and also hold a boolean attribute such 'running = true/false'. That way if in the middle of you long-running request, someone tries to invoke the same process again, they will be able to know if it's running already. Now that's more details than you asked for.

Anyway, I hope I helped and at the same time gave you clues as to how to move forward.

Can we use jquery ajax for this

success: function(xhr_data) {
  console.log(xhr_data);
  if (xhr_data.status == 'pending') {

    if (cnt < 6) {
        cnt++;
        setTimeout(function() { ajax_request(); }, 15000); // wait 15 seconds than call ajax request again
    }

  } else {
    success(xhr_data);
  }
}

I would consider a push notification SaaS like http://pusher.com/

Client sends request to server that takes a while:

POST /process-file

Server responds

HTTP 202 Accepted

{ channelName:'some-channel', events:[{name:'my-processing-complete-event'}] }

On the client, in JavaScript, subscribe to channel and listen:

var channel = pusher.subscribe('some-channel');
channel.bind('my-processing-complete-event', function(message){
  alert(message);
});

On the server, when the processing is complete, you notify your push service, which then notifies all clients.

pusher.trigger("some-channel", "my-processing-complete-event", "processing done");

I think that the best solution is as follows. Have a DB table that monitors back end tasks. Periodically the front end queries this table through a back end service for the status. Once the status is complete then it informs the user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM