3

Spontaneously the answer is of course no, so to understand what I'm getting at please let me explain.

We have a service into which the client POSTs jobs that are to be executed, but they are not executed at the time of the post. Instead our service responds with an ID which the client may use to execute the job via a GET.

Now when the job is executed, it is also removed and that job is no longer available.

From my understanding of what a RESTfull architecture is, our implementation does not comply to the ideas of REST.

So what I'm wondering is, if were not RESTfull how should we redesign so that we are? Is it just a matter of changing our GET to POST (which i don't believe, since were removing something (the job)) at the same time a DELETE also seems weird since were executing a job

with job I mean that we're providing a possibly huge amount of data from our DB's.

Daniel Figueroa
  • 10,348
  • 5
  • 44
  • 66
  • This question appears to be off topic for stackoverflow – Ryan Jul 16 '14 at 14:47
  • 1
    He is asking for help in redesign... that seems very stack overflowish – AnthonyJClink Jul 16 '14 at 14:54
  • I'd argue you're not removing the job, and that the resource representation of the job isn't the job itself, but rather the job execution status. My guess is that you have no need to remove the execution status of a job, so a POST would be appropriate. A PUT could also work. – Jonathan W Jul 18 '14 at 03:46

3 Answers3

2

our service responds with an ID which the client may use to execute the job via a GET.

That sounds like not RESTful. The client should PUT to the job resouce, perhaps setting the job status to execute.

PUT /jobs/1234
{
   "status": "execute"
}

200 OK

The client can later GET the job resource to check the status. Maybe later the status will change to completed.

GET /jobs/1234

200 OK
{
   "id": 1234,
   "status": "completed",
   "quizzle": "smooth"
}

If after some time some different part of the system removes completed jobs, a GET to the job resource would result in a 410 Gone.

GET /jobs/1234

410 Gone
  • My concern with this solution is you're conflating the job and the job results in one resource. What if there is a new requirement for the job to be run more than once? You'd need to make the execution data part of an internal JSON array for the job. – Eric Stein Jul 16 '14 at 14:39
  • 1
    That is a valid point. My assumption is that a job can be run only once. If a job mit identical parameters is created later, it is a different job. –  Jul 16 '14 at 14:41
  • @Tichodroma your assumption is correct. Our problem is that we do not want to store the result on the server (a second time since it is available in our databases, it would be to resource intensive). So we need to get the data, and once the data is retrieved it shouldn't be accessible (410 as you suggest seems very good). Wether we should use PUT or POST I'll just refer to this thread: http://stackoverflow.com/questions/630453/put-vs-post-in-rest – Daniel Figueroa Jul 16 '14 at 15:47
2

Being RESTfull is a great discussion, the main concept behind which is expressing resources using the URI and actions using HTTP verbs. I would propose the following three solutions, from the most preferred in my opinion to the least one.

  1. You could do a PATCH request, which will change a field in the job - i.e. status from waiting to running - which will fire a signal on your backend and start the job. Subsequent PATCH requests could return a 400 or 409 response code.
  2. You could do a POST request to /jobs/:job_id/execute/ which will start executing the job. Responses could be as above.
  3. You could add a side effect to you GET request - this is your job execution - which will change the status to executing the first time it is called.

Hope this helps, it's a great discussion topic :)

akalipetis
  • 938
  • 1
  • 7
  • 14
  • 1
    2 and 3 are not RESTful. 2 uses a verb (execute) in the URL. 3 makes the GET non-idempotent and non-safe. – Eric Stein Jul 16 '14 at 14:36
  • Thanks for the correction Eric, though in such cases, being completely RESTfull is not always the easiest way to go. That's why I started with the most preferred answer (1). – akalipetis Jul 16 '14 at 14:41
0

No. Don't execute the job via a get. If the job has already been executed and somebody tries to POST it again, return a 422 Unprocessable Entity with an explanation that the job has already been run. If you really must, you can delete the job on the second post. Better to let the client decide if/when to delete the job.

send up a job:
POST /jobs
{ .. }

execute a job:
POST /executed-jobs
==> { "jobId": 12345 }
<== { "expectedCompletionTime": "<timestamp>" }
Eric Stein
  • 13,209
  • 3
  • 37
  • 52