Search code examples
flaskflask-sqlalchemyflask-socketio

flask_socketio & flask_sqlalchemy - socketio.emit() is blocked when flask_sqlalchemy is querying / committing


Here's a test block of code that can be used to repeat the issue I'm experiencing

from gevent import monkey as curious_george
curious_george.patch_all(thread=True)

from flask_socketio import SocketIO
from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)


app.config['SQLALCHEMY_DATABASE_URI'] = "my_custom_uri"
app.config['SQLALCHEMY_POOL_SIZE'] = 20
app.config['SQLALCHEMY_MAX_OVERFLOW'] = 50

db = SQLAlchemy(app)
socketio = SocketIO(app)

class test_table(db.Model):
    _id = db.Column("id",db.Integer,primary_key=True)
    flagged = db.Column("flagged",db.Boolean(), default=False)

    def __init__(self,flagged):
        self.flagged = flagged

@app.route('/test')
def test_route():
      for x in range(100):
            test_flag = db.session.query(test_table).filter_by(_id=1).first()
            test_flag.flagged = not test_flag.flagged
            db.session.commit()
            # print(x)
            socketio.emit('x_test',x, broadcast=True)

      return("success",200)


if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=8080)

The database commits happen first and once they finish all of the socketio emits dump (in order) at once.

Maybe I have something misconfigured? Does sqlalchemy need to be handled in a more concurrent method?

I just reinstalled my virtual environment for other reasons

Flask-Socketio 5.2.0 python-engineio 4.3.4 python-socketio 5.7.2 gevent 22.10.2 gevent-websocket 0.10.1

I don't have any related warnings on the flask server startup

I expected the socketio emits to happen in time with the database query commits


Solution

  • Turns out I needed to patch psycopg2 as well using the "psycogreen" library

    I used this patch to fix it, and it works now.

    from psycogreen import gevent
    gevent.patch_psycopg()