简体   繁体   English

铁工作业完成通知

[英]Ironworker job done notification

I'm writing python app which currently is being hosted on Heroku. 我正在编写当前托管在Heroku上的python应用。 It is in early development stage, so I'm using free account with one web dyno. 它处于早期开发阶段,因此我正在使用带有一个Web dyno的免费帐户。 Still, I want my heavier tasks to be done asynchronously so I'm using iron worker add-on. 尽管如此,我还是希望异步执行较重的任务,因此我正在使用Iron Worker附加组件。 I have it all set up and it does the simplest jobs like sending emails or anything that doesn't require any data being sent back to the application. 我已完成所有设置,它完成了最简单的工作,例如发送电子邮件或不需要将任何数据发送回应用程序的任何操作。 The question is: How do I send the worker output back to my application from the iron worker? 问题是:如何将铁工人的工人输出发送回我的应用程序? Or even better, how do I notify my app that the worker is done with the job? 甚至更好的是,如何通知我的应用程序该工作人员已经完成工作?

I looked at other iron solutions like cache and message queue, but the only thing I can find is that I can explicitly ask for the worker state. 我看了其他诸如缓存和消息队列之类的解决方案,但是我唯一能找到的就是我可以明确地要求工作者状态。 Obviously I don't want my web service to poll the worker because it kind of defeats the original purpose of moving the tasks to background. 显然,我不希望我的Web服务轮询该工作程序,因为这违反了将任务移至后台的最初目的。 What am I missing here? 我在这里想念什么?

I see this question is high in Google so in case you came here with hopes to find some more details, here is what I ended up doing: 我认为这个问题在Google中很普遍,因此如果您希望找到更多详细信息,这就是我最后要做的事情:

First, I prepared the endpoint on my app. 首先,我在应用程序上准备了端点。 My app uses Flask , so this is how the code looks: 我的应用程序使用Flask ,因此代码如下所示:

@app.route("/worker", methods=["GET", "POST"])
def worker():
#refresh the interface or whatever is necessary
    if flask.request.method == 'POST':
        return 'Worker endpoint reached'
    elif flask.request.method == 'GET':
        worker = IronWorker()
        task = worker.queue(code_name="hello", payload={"WORKER_DB_URL": app.config['WORKER_DB_URL'],
                            "WORKER_CALLBACK_URL": app.config['WORKER_CALLBACK_URL']})
        details = worker.task(task)
        flask.flash("Work queued, response: ", details.status)
        return flask.redirect('/')

Note that in my case, GET is here only for testing, I don't want my users to hit this endpoint and invoke the task. 请注意,就我而言,GET仅在此处用于测试,我不希望我的用户点击此端点并调用任务。 But I can imagine situations when this is actually useful, specifically if you don't use any type of scheduler for your tasks. 但是我可以想象这种情况实际上有用的情况,特别是如果您不为任务使用任何类型的调度程序。

With the endpoint ready, I started to look for a way of visiting that endpoint from the worker. 准备好端点之后,我开始寻找一种从工作人员访问该端点的方法。 I found this fantastic requests library and used it in my worker: 我找到了这个很棒的请求库 ,并在我的工作程序中使用了它:

import sys, json
from sqlalchemy import *
import requests

print "hello_worker initialized, connecting to database..."

payload = None
payload_file = None
for i in range(len(sys.argv)):
    if sys.argv[i] == "-payload" and (i + 1) < len(sys.argv):
        payload_file = sys.argv[i + 1]
        break

f = open(payload_file, "r")
contents = f.read()
f.close()

payload = json.loads(contents)

print "contents: ", contents
print "payload as json: ", payload

db_url = payload['WORKER_DB_URL']

print "connecting to database ", db_url

db = create_engine(db_url)
metadata = MetaData(db)

print "connection to the database established"

users = Table('users', metadata, autoload=True)
s = users.select()

#def run(stmt):
#    rs = stmt.execute()
#    for row in rs:
#        print row

#run(s)

callback_url = payload['WORKER_CALLBACK_URL']
print "task finished, sending post to ", callback_url
r = requests.post(callback_url)
print r.text

So in the end there is no real magic here, the only important thing is to send the callback url in the payload if you need to notify your page when the task is done. 因此,最后没有真正的魔力,唯一重要的是,如果您需要在完成任务时通知页面,则在有效负载中发送回调URL。 Alternatively you can place the endpoint url in the database if you use one in your app. 或者,如果在应用程序中使用端点URL,则可以将端点URL放置在数据库中。 Btw. 顺便说一句。 the snipped above also shows how to connect to the postgresql database in your worker and print all the users. 上面的摘录还显示了如何连接到worker中的postgresql数据库并打印所有用户。

One last thing you need to be aware of is how to format your .worker file, mine looks like this: 您需要了解的最后一件事是如何格式化.worker文件,我的看起来像这样:

# set the runtime language. Python workers use "python"
runtime "python"
# exec is the file that will be executed:
exec "hello_worker.py"
# dependencies
pip "SQLAlchemy"
pip "requests"

This will install the latest versions of SQLAlchemy and requests, if your project is dependent on any specific version of the library, you should do this instead: 这将安装最新版本的SQLAlchemy和请求,如果您的项目依赖于该库的任何特定版本,则应该执行以下操作:

pip "SQLAlchemy", "0.9.1"

最简单的方法-从工作人员将消息推送到您的api-它是日志或您应用程序中需要的任何内容

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

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