我正在设计一个任务队列休息界面,并想知道最佳实践。
一个操作是接受队列中的“下一个”任务。
通过接受工作,只有第一个工人才能得到这份工作。
在接受工作之前,工作人员不会知道任务或任务ID。
现在我想我不能使用GET,因为它不是幂等的。如果两次调用nextTask,你会得到两个不同的工作。所以我想它应该是一个POST。
POST // rest / taskqueue?action = acceptTask
或者我是以错误的方式看待它?
答案 0 :(得分:3)
基本上:
我就是这样做的。
排队新任务:
--> POST http://api.crazyjoes.com/v1/tasks/
--> {"data":{"lulcat":true}}
<-- 202 Accepted
使用特定ID排队新任务:
--> PUT http://api.crazyjoes.com/v1/tasks/393ee7f6-c44a-4b34-86ac-92c9f31a4bc6/
--> {"data":{"lulcat":true}}
<-- 202 Accepted
检索最早的任务:
--> GET http://api.crazyjoes.com/v1/tasks/oldest/
<-- 200 OK
<-- {"id":123,"data":{"lulcat":true}}
如果队列为空:
--> GET http://api.crazyjoes.com/v1/tasks/oldest/
<-- 204 No Content
将特定任务出列:
--> DELETE http://api.crazyjoes.com/v1/tasks/123/
<-- 200 OK
<-- {"id":123,"data":{"lulcat":true}}
如果任务已经处理......
--> DELETE http://api.crazyjoes.com/v1/tasks/123/
<-- 410 Gone
如果您想直接将最旧的项目出列...
--> DELETE http://api.crazyjoes.com/v1/tasks/oldest/
<-- 200 OK
<-- {"id":123,"data":{"lulcat":true}}
答案 1 :(得分:1)
怎么样:
/tasks
和/tasks/{taskId}
分别是所有任务和单个任务的通常集合。
/tasksqueue
是队列中的任务,而/tasksqueue/top
是队列的顶部,只支持GET。我们假设所有任务都有唯一的ID。
然后发出GET /tasksqueue/top
以获取队列顶部的任务ID,并发出DELETE /tasksqueue/{taskId}
以尝试将其从队列中弹出。
如果失败,即返回非20x,则表示其他人在您的呼叫之间弹出队列。
如果成功,它将在其身体中返回任务,您可以使用它完成任务,知道您已成功弹出它。或者,因为您知道其ID,您可以从/tasks/{taskId}
获取任务信息。
不应该多次成功。
你可以多次发布DELETE /tasksqueue/{taskId}
,对系统的整体效果与其中一个一样,因此DELETE
正在按照它应有的方式行事。 (除了第一个DELETE
调用之外的所有或所有调用都返回非20x的事实并没有改变这一事实。)
答案 2 :(得分:0)
POST是“附加”动词,也是HTTP规范的“数据处理”动词。因此,从概念上讲,您将任务附加到任务列表以进行处理。 POST恰到好处。
GET不正确的另一个原因是因为GET不应该对资源进行更改。但传入的请求 将进行更改...它将添加一个项目。
我会放弃“action = acceptTask”。在REST中,HTTP谓词指定您的意图,URI指定目标。所以你正在做的是将新任务附加到队列......“action”参数不会添加任何内容。
通常,如果要为请求提供其他信息,可以添加参数以提供有关操作的修饰符。但另一种惯例是或多或少地作弊,然后将意图放在URI的末尾并将其视为子资源(即代替参数)。 e.g:
ht_p://.../taskqueue/fold
ht_p://.../taskqueue/roll
ht_p://.../taskqueue/rattle
(hm. not sure how many things you can actually do with a queue...)
但是,你永远不应该复制HTTP动词...这是对底层协议的滥用和REST中的禁忌:
ht_p://.../taskqueue/get
ht_p://.../taskqueue/update
ht_p://.../taskqueue/delete
...ack!