2

I am developing a RESTful web service using flask-restful.

The client needs to be able to request a job to be performed by the server. This job can take anywhere from ~1 second to ~1 hour to perform. Generally, it is expected to take 1-5 minutes.

When the job is complete, the client needs to download a JSON dump. Anywhere from 100KB to 100MB in size.

I see 2 options:

  1. The client submits the job as a POST request, and the response from the server only comes when the job is complete. The response includes the JSON dump.
  2. The client submits the job as a POST request, and the server responds immediately with a 200 OK. The client then submits a GET status request every, say, 60 seconds. When the job is complete, it submits another GET request to download the JSON dump.

Which option is preferred under REST principles?

The problem I see with Option 1 is the possibility of network disruption whilst waiting for the response.

edanfalls
  • 440
  • 7
  • 15
  • 1
    Imagine 10 clients waiting for the response when you pick option 1. Now scale that to 100 clients, 1000, etc. How quickly will your server run out of resources to handle all those connections? How quickly if they don't wait for the job to complete and instead are given a job number to poll? – Martijn Pieters Apr 27 '16 at 11:13
  • 2
    You should respond 202, not 200: *"The 202 (Accepted) status code indicates that the request has been accepted for processing, but the processing has not been completed."* This response can then include a payload with information like estimated time for completion, where to look for the result, etc. See e.g. http://farazdagi.com/blog/2014/rest-long-running-jobs/ – jonrsharpe Apr 27 '16 at 11:31
  • @MartijnPieters: Good question. The job is fairly resource (CPU/mem) intensive. Therefore, I don't see a big difference in resources with either option. At most a few thousand connections, so I do not expect to saturate Flask with that. – edanfalls Apr 27 '16 at 11:34
  • 1
    Note that the short answer is no: your server should respond as quickly as possible with information on what is happening and what, if anything, the client should do next. Sometimes that's an immediate 200/201, sometimes (if you know it will take a while) that's an immediate 202 then the client can make additional requests for state updates. – jonrsharpe Apr 27 '16 at 11:37
  • I think this has already been answered in several places on SO - am I missing something? e.g. http://stackoverflow.com/questions/33009721/long-running-rest-api-with-queues.and https://stackoverflow.com/questions/16470290/long-running-rest-api. – Charlie Apr 27 '16 at 13:39

1 Answers1

7

Waiting more than a few seconds is an absolute no-no.

Most of the web infrastructure is not designed to handle such long delays, and some proxies/load balancers may timeout - even if your server finally produces the response, no-one will be there to read it. Moreover, the user will get bored and start refreshing/cancelling/whatever.

As @jonrsharpe mentioned in the comment, your server should respond as quickly as possible with information on what's happening. Enter 202 Accepted status code:

The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility for re-sending a status code from an asynchronous operation such as this.

(taken from restapitutorial)

So respond with 202 and a handle to where the results should be - either in body or in response headers. Then the client can poll given location to see the job status and download the results.

If the result is big, it's also reasonable to allow HEAD requests on the result, so that the user can poll HEAD to check if the results are available and then download them with GET, without being suddenly flooded during the polling.

Wojciech Ptak
  • 683
  • 4
  • 14