Это не обязательно конкретный ответ, но вместо того, чтобы помещать вещи в комментарии, я помещу его здесь.
Celery - менеджер задач для python. Причина, по которой вы захотите использовать это, заключается в том, что если у вас есть задачи, проверяющие Flask, но они требуют больше времени, чем интервал между входящими задачами, тогда определенные задачи будут заблокированы, и вы не получите все свои результаты. Чтобы это исправить, вы передаете его другому процессу. Это выглядит так:
1) Client sends a request to Flask to process audio files
2) The files land in Flask to be processed, Flask will send an asyncronous task to Celery.
3) Celery is notified of the task and stores its state in some sort of messaging system (RabbitMQ and Redis are the canonical examples)
4) Flask is now unburdened from that task and can receive more
5) Celery finishes the task, including the upload to your database
Celery и Flask - это два отдельных процесса Python, взаимодействующих друг с другом. Это должно удовлетворить ваш многопоточный подход. Вы также можете получить состояние из задачи через Flask, если хотите, чтобы клиент проверял, что задача была / не была выполнена. Маршрут в вашей колбе app.py
будет выглядеть так:
@app.route('/my-route', methods=['POST'])
def process_audio():
# Get your files and save to common temp storage
save_my_files(target_dir, files)
response = celery_app.send_tast('celery_worker.files', args=[target_dir])
return jsonify({'task_id': response.task_id})
Где celery_app
происходит из другого модуля worker.py
:
import os
from celery import Celery
env = os.environ
# This is for a rabbitMQ backend
CELERY_BROKER_URL = env.get('CELERY_BROKER_URL', 'amqp://0.0.0.0:5672/0')
CELERY_RESULT_BACKEND = env.get('CELERY_RESULT_BACKEND', 'rpc://')
celery_app = Celery('tasks', broker=CELERY_BROKER_URL, backend=CELERY_RESULT_BACKEND)
Тогда ваш процесс сельдерея настроит работника что-то вроде:
from celery import Celery
from celery.signals import after_task_publish
env = os.environ
CELERY_BROKER_URL = env.get('CELERY_BROKER_URL')
CELERY_RESULT_BACKEND = env.get('CELERY_RESULT_BACKEND', 'rpc://')
# Set celery_app with name 'tasks' using the above broker and backend
celery_app = Celery('tasks', broker=CELERY_BROKER_URL, backend=CELERY_RESULT_BACKEND)
@celery_app.task(name='celery_worker.files')
def async_files(path):
# Get file from path
# Process
# Upload to database
# This is just if you want to return an actual result, you can fill this in with whatever
return {'task_state': "FINISHED"}
Это относительно просто, но может послужить отправной точкой. Я скажу, что некоторые настройки и настройки Celery не всегда наиболее интуитивны, но это сделает ваше приложение фляги доступным для тех, кто хочет отправлять на него файлы, не блокируя ничего другого.
Надеюсь, это несколько полезно