9

I have a web application which acts as an interface to an offsite server which runs a very long task. The user enters information and hits submit and then chrome waits for the response, and loads a new webpage when it receives it. However depending on the network, input of the user, the task can take a pretty long time and occasionally chrome loads a "no data received page" before the data is returned (though the task is still running).

Is there a way to put either a temporary page while my task is thinking or simply force chrome to continue waiting? Thanks in advance

sedavidw
  • 11,116
  • 13
  • 61
  • 95

3 Answers3

16

While you could change your timeout on the server or other tricks to try to keep the page "alive", keep in mind that there might be other parts of the connection that you have no control over that could timeout the request (such as the timeout value of the browser, or any proxy between the browser and server, etc). Also, you might need to constantly up your timeout value if the task takes longer to complete (becomes more advanced, or just slower because more people use it).

In the end, this sort of problem is typically solved by a change in your architecture.

Use a Separate Process for Long-Running Tasks

Rather than submitting the request and running the task in the handling view, the view starts the running of the task in a separate process, then immediately returns a response. This response can bring the user to a "Please wait, we're processing" page. That page can use one of the many push technologies out there to determine when the task was completed (long-polling, web-sockets, server-sent events, an AJAX request every N seconds, or the dead-simplest: have the page reload every 5 seconds).

Have your Web Request "Kick Off" the Separate Process

Anyway, as I said, the view handling the request doesn't do the long action: it just kicks off a background process to do the task for it. You can create this background process dispatch yourself (check out this Flask snippet for possible ideas), or use a library like Celery or (RQ).

Once the task is complete, you need some way of notifying the user. This will be dependent on what sort of notification method you picked above. For a simple "ajax request every N seconds", you need to create a view that handles the AJAX request that checks if the task is complete. A typical way to do this is to have the long-running task, as a last step, make some update to a database. The requests for checking the status can then check this part of the database for updates.

Advantages and Disadvantages

Using this method (rather than trying to fit the long-running task into a request) has a few benefits:

1.) Handling long-running web requests is a tricky business due to the fact that there are multiple points that could time out (besides the browser and server). With this method, all your web requests are very short and much less likely to timeout.

2.) Flask (and other frameworks like it) is designed to only support a certain number of threads that can respond to web queries. Assume it has 8 threads: if four of them are handling the long requests, that only leaves four requests to actually handle more typical requests (like a user getting their profile page). Half of your web server could be tied up doing something that is not serving web content! At worse, you could have all eight threads running a long process, meaning your site is completely unable to respond to web requests until one of them finishes.

The main drawback: there is a little more set up work in getting a task queue up and running, and it does make your entire system slightly more complex. However, I would highly recommend this strategy for long-running tasks that run on the web.

Mark Hildreth
  • 42,023
  • 11
  • 120
  • 109
0

I believe this is due to your web server (apache in most cases) which has a timeout to small. Try to increase this number

For apache, have a look at the timeout option

EDIT: I don't think you can do set this time out in Chrome (see this topic on google forums even though it's really old) In firefox, on the about:config page, type timeout and you'll have some options you can set. I have no idea about Internet Explorer.

Paco
  • 4,520
  • 3
  • 29
  • 53
  • Perhaps my question wasn't perfectly clear, I don't think the server is timing out (though for completeness I'm using werkzeug...the default in flask). The server is still processing and will use a POST eventually, but chrome has already defaulted to a "no data returned" page. I have updated the question to clear this up – sedavidw Aug 08 '13 at 15:20
  • @sedavidw were you able to find a solution to this problem. I've been facing the same problem and have tried multiple things. None worked. – nEO Feb 10 '16 at 13:24
  • @nEO the answer marked as a solution worked for me. In my case I kicked off a celery task, loaded an "intermittent web page" that checked on the status of task with jQuery, and when it was done would load the results – sedavidw Feb 10 '16 at 13:44
0

Let's assume:

  1. This is not a server issue, so we don't have to go fiddle with Apache, nginx, etc. timeout settings.

  2. The delay is minutes, not hours or days, just to make the scenario manageable.

  3. You control the web page on which the user hits submit, and from which user interaction is managed.

If those obtain, I'd suggest not using a standard HTML form submission, but rather have the submit button kick off a JavaScript function to oversee processing. It would put up a "please be patient...this could take a little while" style message, then use jQuery.ajax, say, to call the long-time-taking server with a long timeout value. jQuery timeouts are measured in milliseconds, so 60000 = 60 seconds. If it's longer than that, increase your specified timeout accordingly. I have seen reports that not all clients will allow super-extra-long timeouts (e.g. Safari on iOS apparently has a 60-second limitation). But in general, this will give you a platform from which to manage the interactions (with your user, with the slow server) rather than being at the mercy of simple web form submission.

There are a few edge cases here to consider. The web server timeouts may indeed need to be adjusted upward (Apache defaults to 300 seconds aka 5 minutes, and nginx less, IIRC). Your client timeouts (on iOS, say) may have maximums too low for the delays you're seeing. Etc. Those cases would require either adjusting at the server, or adopting a different interaction strategy. But an AJAX-managed interaction is where I would start.

Jonathan Eunice
  • 21,653
  • 6
  • 75
  • 77