开发者

RESTful Job Assignment

开发者 https://www.devze.com 2023-01-24 04:35 出处:网络
I have a collection of jobs that need processing, http://example.com/jobs. Each job has a status of \"new\", \"assigned\" or \"finished\".

I have a collection of jobs that need processing, http://example.com/jobs. Each job has a status of "new", "assigned" or "finished".

I want slave processes to pick off one "new" job, set it's status to "assigned", and then process it. I want to ensure each job is only processed by a single slave.

I considered having开发者_开发百科 each slave do the following:

  1. GET http://example.com/jobs
  2. Pick one that's "new" and do an http PUT to http://example.com/jobs/123 {"status=assigned"}.
  3. Repeat

The problem is that another slave may have assigned the job to itself between the GET and PUT. I could have the second PUT return a 409 (conflict), which would signal the second slave to try a different job.

Am I on the right track, or should I do this differently?


I would have one process that picks "new" jobs and assigns them. Other processes would independently go in and look to see if they've been assigned a job. You'd have to have some way to identify which process a job is assigned to, so some kind of slave process id would be called for.


(You could use POST too, as what you're trying to do shouldn't be idempotent anyway).

You could give each of your clients a unique ID (possibly a UUID) and have an "assignee/worker" field in your job resource.

  1. GET http://example.com/jobs/
  2. POST { "worker"=$myID } to http://example.com/jobs/123
  3. GET http://example.com/jobs/123 and check that the worker ID is that of the client

You could combine this with conditional requests too.

On top of this, you could have a time out feature if the job queue doesn't hear back from a given client, it puts it back in the queue.


It looks that the statuses are an essential part of your job-domain model. So I would expose this as dedicated sub-resources


# 'idle' is what you called 'new'
GET /jobs/idle
GET /jobs/assigned

# start job
PUT /jobs/assigned/123

Slave is only allowed to gather jobs by GET /jobs/idle. This never includes jobs which are running. Still there could be race conditions (two slaves are getting the set, before one them has started job). I think 400 Bad Request or your mentioned 409 Conflict are alright with that.

I prefer above resource-structure instead of working with payloads (which often looks more "procedural" to me).


I was a little to specific, I don't actually care that the slave gets to pick the job, just that it gets a unique one.

With that in mind, I think @manuel aldana was on the right track, but I've made a few modifications.

I'll keep the /jobs resource, but also expose a /jobs/assigned resource. A single job may exist in both collections.

The slave can POST to /jobs/assigned with no parameters. The server will choose one "new" job, move it to "assigned", and return the url (/jobs/assigned/{jobid} or /jobs/{jobid}) in the Location header with a 201 status.

When the slave finishes the job, it will PUT to /jobs/{jobid} (status=finished).

0

精彩评论

暂无评论...
验证码 换一张
取 消