2013-01-12 35 views
4

我正在设计一个任务队列休息界面,并想知道最佳实践。任务队列的休息设计

一个动作是接受队列中的“下一个”任务。

通过接受工作,只有第一名工人才能得到这份工作。

工作人员直到接受任务才会知道任务或任务ID。

现在我想我不能使用GET,因为它不是幂等的。如果调用nextTask两次,你会得到两个不同的工作。所以我想它应该是一个POST。

POST //休息/任务队列?行动= acceptTask

还是我看着它的错误的方式?

回答

2

基本上是:

  • GET - 在不修改资源的情况下读取数据(idempotent)。您可以根据需要执行尽可能多的GET操作,但不会修改资源。
  • PUT - 明确在资源提出数据(不幂等)
  • POST - 在资源追加数据(不幂等)
  • DELETE - 从资源删除数据(不幂等)

这是我该怎么做的。

排队一个新的任务:

--> 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}} 
+0

感谢您的回答,这是有道理的。其实我想的不是立即从队列中删除任务,而是将状态从NEW更改为ACCEPTED,然后在完成后更改为COMPLETED。这样我可以跟踪被接受但从未完成的任务,以便在需要时将它们放回队列中。在这种情况下,我可以发送409个冲突,而不是410个。或者像你所建议的另一张接受/待决/完成的工作表一样,并发送410. –

+2

嗯,这个设计似乎并不像OP所要求的那样:“通过接受工作只有第一名工人才能得到这份工作” 。两名工作人员可以独立抓取最老的任务,因为这种设计不会将任务出列或将其标记为在提取最早的任务时声明。建议: - > POST http://api.crazyjoes。com/v1/task_distributor < - 200 OK 返回和出队(或标记为“声明”)最早的任务。 –

0

POST是“追加”动词,也是根据HTTP规范的“数据处理”动词。因此,从概念上讲,您将任务追加到任务列表中进行处理。 POST是正确的。

GET不正确的另一个原因是因为GET不应该对资源进行更改。但传入的请求要进行更改...它将添加一个项目。

我会放弃“action = acceptTask”。在REST中,HTTP动词指定您的意图,并且URI指定目标。所以你正在做的是将一个新任务添加到队列中......“action”参数不会添加任何内容。

通常,如果您想为请求提供附加信息,则可以添加参数以提供有关如何操作的修饰符。但另一个约定是或多或少地作弊,并将其意图放在URI的末尾,并将其视为子资源(即,而不是参数)。例如:

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! 
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不会改变该事实。)

+0

如果两名不同的员工不能完成相同的任务真的很重要,这是一个好方法。然而,当删除完成(即一个项目被弹出)时,存在一种风险,因为某种原因它并未实际完成。 一个变体是发送整个项目获取,然后用删除确认其完成。然而,这可能会导致两名工人得到相同的物品然后重复工作。 猜猜你会选择取决于重复的工作是多么糟糕,以及你的应用程序中丢失的项目有多糟。除非有办法解决这两种情况? –