由于没有人提供this post的解决方案以及我迫切需要解决方法的事实,这里是我的情况和一些抽象的解决方案/想法供辩论。
我的筹码:
我的问题:为Tornado找一种方法来发送芹菜任务(已解决),然后异步收集结果(任何想法?)。
场景1 :(请求/响应黑客加上webhook)
这可能发生吗?它有任何逻辑吗?
情景2 :(龙卷风加长轮询)
效率这么高吗?
还有其他想法/架构吗?
答案 0 :(得分:9)
我的解决方案涉及从龙卷风到芹菜的轮询:
class CeleryHandler(tornado.web.RequestHandlerr):
@tornado.web.asynchronous
def get(self):
task = yourCeleryTask.delay(**kwargs)
def check_celery_task():
if task.ready():
self.write({'success':True} )
self.set_header("Content-Type", "application/json")
self.finish()
else:
tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check_celery_task)
tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check_celery_task)
以下是post。
答案 1 :(得分:8)
这是我们解决问题的方法。由于我们在应用程序中查找了几个处理程序的结果,因此我们将芹菜查找为mixin类。
这也使得tornado.gen模式的代码更具可读性。
from functools import partial
class CeleryResultMixin(object):
"""
Adds a callback function which could wait for the result asynchronously
"""
def wait_for_result(self, task, callback):
if task.ready():
callback(task.result)
else:
# TODO: Is this going to be too demanding on the result backend ?
# Probably there should be a timeout before each add_callback
tornado.ioloop.IOLoop.instance().add_callback(
partial(self.wait_for_result, task, callback)
)
class ARemoteTaskHandler(CeleryResultMixin, tornado.web.RequestHandler):
"""Execute a task asynchronously over a celery worker.
Wait for the result without blocking
When the result is available send it back
"""
@tornado.web.asynchronous
@tornado.web.authenticated
@tornado.gen.engine
def post(self):
"""Test the provided Magento connection
"""
task = expensive_task.delay(
self.get_argument('somearg'),
)
result = yield tornado.gen.Task(self.wait_for_result, task)
self.write({
'success': True,
'result': result.some_value
})
self.finish()
答案 2 :(得分:4)
我偶然发现了这个问题,并且反复对结果进行后续检查对我来说并不是最佳选择。所以我使用Unix套接字实现了类似于你的场景1的Mixin。
一旦任务完成,它就会通知龙卷风(准确地说,只要链中的下一个任务运行),并且只会在后端点击一次结果。这是link。
答案 3 :(得分:3)
现在,https://github.com/mher/tornado-celery来救援......
class GenAsyncHandler(web.RequestHandler):
@asynchronous
@gen.coroutine
def get(self):
response = yield gen.Task(tasks.sleep.apply_async, args=[3])
self.write(str(response.result))
self.finish()