我正在尝试将事件从 Celery 任务发送到服务器,以便我可以向客户端发送数据。
这是我目前拥有的:
routes.py
@main_bp.route('/', methods=['GET', 'POST'])
def index():
form = UserTextForm()
if request.method == 'POST':
request_data = request.form.to_dict()
user_text = request_data['user_text']
run_processing_task.apply_async(args=[user_text])
return render_template('index.html', form=form)
@socketio.on('my_event', namespace='/user_text_task_results')
def user_test_task_results(my_event):
# Sends data to client
send(my_event, broadcast=True)
celery_tasks.py
@celery.task(bind=True)
def run_processing_task(self, user_text):
print('Celery Function kicked off')
local_socketio = SocketIO(message_queue='redis://localhost:6379/0')
time.sleep(3)
user_text_reverse = user_text[::-1]
local_socketio.emit('my_event', {'data': user_text_reverse}, namespace='/user_text_task_results')
print('Task Completed')
return 'Finished'
index.html
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Welcome</h1>
</head>
<form method="POST" action="{{ url_for('main_bp.index') }}" class="col-6">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.user_text(class="form-control", id="user-text-area") }}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="test-app">
</div>
<script>
$(document).ready(function() {
var socket = io.connect('http://127.0.0.1:5000');
socket.on('connect', function() {
socket.send('User Connected')
});
socket.on('message', function(results){
var reversed_text = results['data']
$("$test-app").append('<p>'+reversed_text+</p>)
});
});
</script>
当我运行上面的时候,任务被处理了,但是我认为服务器没有收到数据local_socketio.emit(...)
。我可以看到 Celery 任务成功完成,但我没有看到任何迹象表明数据流向服务器并最终流向客户端。
我尝试安装 gevent 和 gevent-websocket,但随后索引不会为初始 GET 请求事件加载(它只是挂在加载状态)
答案 0 :(得分:1)
Celery 工作人员通常运行与 Flask 应用程序相同的代码,但它们不作为flask 服务器运行,因此从celery 到flask 的websocket 并不是一件容易的事情。 (我从未见过它完成,但也许有人已经解决了棘手的部分。)
假设您想避免让客户端或应用轮询任务完成,另一种方法是通过向应用发出 HTTP 请求来让工作线程完成信号。即,类似于 POST 到
/tasks/complete/<task_id>
然后是一个应用程序问题已经完成了将 task_id
与特定 websocket 相关联的簿记。
添加:
Celery 有一个 post_run 信号,应该用于相同的目的。几年前我运气不好,但现在觉得我做了一些愚蠢的事情。