Tornado 的 RequestHandler 可以接受来自客户端的 POST,将任务添加到队列中,然后响应“ok I got it”:
q = collections.deque()
class MyHandler(RequestHandler):
def post(self):
# Your code determines what work the client requests:
task_info = parse(self.request.body)
q.append(task_info)
self.finish(json.dumps({'ok': 1}))
客户端应生成唯一的 task_id 并将其包含在它发布的信息中。
如果您想要更复杂的任务队列,可以查看my Toro project。或者更简单的方法是使用 Tornado PeriodicCallback 经常检查队列中是否有任务。
那么,您如何通知客户某项任务已完成?如果客户端是浏览器,我建议使用 websocket 连接。这是Tornado's websocket documentation。当有人访问您的页面时,一些 Javascript 应该打开到服务器的 websocket 连接。当访问者提交任务时,Javascript 首先 生成一个 task_id,订阅有关该 task_id 的通知,然后将任务信息发布到服务器。 Javascript:
var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onmessage = function (evt) {
alert(evt.data);
};
/* Tell the server we want to know about this task */
function subscribe(task_id) {
ws.send(JSON.stringify({task_id: task_id}));
}
这是服务器的 websocket 处理程序:
notifiers = set()
class TaskNotifier(websocket.WebSocketHandler):
def open(self):
notifiers.add(self)
def on_message(self, message):
# Client is asking to subscribe to notifications about
# a certain task_id.
parsed = json.loads(message)
self.task_id = parsed['task_id']
def on_close(self):
notifiers.discard(self)
现在,每当您的代码从 q 提取任务并完成它时,它都会执行(在 Python 中):
for n in notifiers:
if n.task_id == task_id:
n.write_message('task %s done' % task_id)
然后浏览器中的 Javascript 客户端检测到它正在等待的任务已经完成。
请注意,客户端在实际将任务提交给服务器之前订阅有关任务的通知;这确保了没有竞争条件,即使服务器很快完成任务。