简体   繁体   English

如何用Ruby推送Celery任务

[英]How to push Celery tasks with Ruby

In our app we have a Rails app that makes an API call to a Flask API. The API then schedules a task, and we are using Redis as the queue.在我们的应用程序中,我们有一个 Rails 应用程序,它会调用 API 调用 Flask API。然后 API 会安排一个任务,我们使用 Redis 作为队列。

@app.route("/api/article", methods=["POST"])
def api_article():
    app.logger.info("[route] /api/article")
     .
     .
    res_id = celery.send_task("tasks.text_stats", args=[article], kwargs={}).id
@celery.task(name="tasks.text_stats")
def text_stats(article):
    logger.info("text_stats")

What I am thinking is if the Redis database is accessible to both Rails and Flask, we could just create the task directly in Redis, which would then be picked up by the Celery worker.我在想的是,如果 Rails 和 Flask 都可以访问 Redis 数据库,我们可以直接在 Redis 中创建任务,然后由 Celery 工作人员接收。

Questions:问题:

  1. How to create a Celery job in Redis using Ruby?如何使用 Ruby 在 Redis 中创建 Celery 作业?
  2. Are there any Ruby libraries which would support this?有没有 Ruby 库支持这个?

To solve this problem we can simply inspect in Redis how Celery pushes tasks to the LIST .为了解决这个问题,我们可以简单地在 Redis 中查看 Celery 是如何将任务推送到LIST的。

This is an example celery task that's been pushed to Redis by Celery:这是一个示例 celery 任务,它已被 Celery 推送到 Redis:

{'body': 'W1siYjVmNDhmNDQtOWZiZS00MjdiLWE3NDMtZjc3MDgwMDQzN2ZiIl0sIHt9LCB7ImNhbGxiYWNrcyI6IG51bGwsICJlcnJiYWNrcyI6IG51bGwsICJjaGFpbiI6IG51bGwsICJjaG9yZCI6IG51bGx9XQ==', 'content-encoding': 'utf-8', 'content-type': 'application/json', 'headers': {'lang': 'py', 'task': 'my_python_function', 'id': '64148470-0dde-4e31-ab63-09c98955d24f', 'shadow': None, 'eta': None, 'expires': None, 'group': None, 'retries': 0, 'timelimit': [None, None], 'root_id': '64148470-0dde-4e31-ab63-09c98955d24f', 'parent_id': None, 'argsrepr': "('my_string_argument_one', 'my_string_argument_2',)", 'kwargsrepr': '{}', 'origin': 'gen73965@mac.local'}, 'properties': {'correlation_id': '64148470-0dde-4e31-ab63-09c98955d24f', 'reply_to': '1a223e51-77c3-37d3-a870-baae15b3b741', 'delivery_mode': 2, 'delivery_info': {'exchange': '', 'routing_key': 'celery'}, 'priority': 0, 'body_encoding': 'base64', 'delivery_tag': 'f840868a-18c9-4b1f-bc95-5ff95666ca21'}}

The more important keys in the above is headers.task , which is the python function name you need to call, as well as headers.argsrepr and headers.kwargsrepr , which is a stringified tuple/dict representing the args/kwargs you need to pass to the function.上面比较重要的键是headers.task ,这是你需要调用的 python function 名称,还有headers.argsreprheaders.kwargsrepr ,这是一个字符串化的元组/字典,代表你需要传递的args/kwargs到 function。

There are other keys in the above dict like routing_key (the celery queue), a couple of ids (you can autogenerate these), eta , that you could use to customize the behavior.上面的dict中还有其他键,例如 routing_key(celery 队列)、几个 id(您可以自动生成这些)、 eta ,您可以使用它们来自定义行为。

Once we understand how celery interacts with Redis, similar to this example , you can simply run LPUSH with Ruby's Redis client with the stringified python dict .一旦我们了解了 celery 如何与 Redis 交互,类似于此示例,您可以简单地使用 Ruby 的LPUSH客户端和字符串化的 python dict运行 LPUSH。

The more troubling part, really, is that celery expects the stringified LIST item to be in dict format, which has some differences with Ruby's to_json .实际上,更麻烦的部分是 celery 期望字符串化的 LIST 项采用dict格式,这与 Ruby 的to_json有一些差异。 You'll need to manually do that part (such as converting booleans to python bool )您需要手动执行该部分(例如将booleans转换为 python bool

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM