Flask-SQLAlchemy QueuePool限制,在单独的线程中进行查询

时间:2019-01-28 11:45:48

标签: python multithreading sqlalchemy flask-sqlalchemy

当我的Flask应用收到请求时,它会生成一个对象,该对象将消息添加到队列中,并在另一个线程上安排队列轮询作业。每两秒钟,对队列进行轮询以查找要发送的消息。某些消息需要数据库查询。在app.py文件中,一个while循环检查消息是否留在队列中,然后休眠直到队列中没有消息,然后提交。

问题是,这引发了QueuePool限制错误。我使用svn检查了PostGreSQL数据库,并且队列轮询作业中的查询在事务中处于空闲状态。我检查了一下,并且所使用的scoped_session始终相同。确实,一旦队列为空,也将调用提交。那么问题可能是什么?

请注意,我使用APScheduler进行调度。

我知道此实现没有意义:我不想在消息之间调用time.sleep(),但还没有意识到我仍然需要阻塞主线程,以便提交能够正常工作。但是,无论实施有多危险,问题仍然是合法的。

简单的例子:

application.py

svnsync

queueing.py

SELECT * FROM pg_stat_activity

config.py

import time
from config import FlaskDatabaseConfig
from queueing import Queue
from flask import Flask
from flask import request
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
application = Flask(__name__)
application.config.from_object(FlaskDatabaseConfig())
db = SQLAlchemy(application)

application.route("/", methods=['GET'])
def handle_req():
    queue = Queue()
    for i in range(3):
         queue.add_message("Test", 1)
    while len(queue.messages) > 0:
         time.sleep(1)
    db.session.commit()

# run the app.
if __name__ == "__main__":
    application.run(debug=False, port=5001)

models.py

from application import db
from models import User
from apscheduler.schedulers.background import BlockingScheduler, BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger

class Queue():
    def __init__(self):
        self.messages =  []
        self.job = None

    def add_message(self, message, recipient_index):
        self.messages.append((message, recipient_index))
        if not self.job:
            scheduler = BackgroundScheduler()
            scheduler.start()
            job = scheduler.add_job(
                func=self.poll_queue,
                trigger=IntervalTrigger(
                    seconds=2
                ),
                id='poll_queue',
                name='The queue is polled every 2 seconds for sending messages',
                replace_existing=True,
                misfire_grace_time=10)
           self.job = job

    def poll_queue(self):
         if len(self.messages)>0:
             msg, recipient_index = self.messages.pop(0)
             recipient = User.query.get(recipient_index)
             self.send_message(msg, recipient)
         else:
             self.job.remove()

    def send_message(self):
        pass

0 个答案:

没有答案