I'm writing a flask app that streams content out to the user, and I'm trying to manipulate the db while this streaming is happening. Here's some example code (simplified):
def work_hard(obj):
yield 'About to do a lot of work...'
obj.status = do_a_lot_of_work_very_slowly()
yield obj.status
db.session.commit()
obj.more = more_slow_stuff()
yield obj.more
db.session.commit()
yield 'Hard work is done!'
@app.route('/log/<int:objid>/work_hard', methods=['POST'])
def perform_action(objid):
obj = MyModel.query.get(objid)
return Response(work_hard(obj), mimetype='text/html')
This code gives the error Instance <MyModel at 0x7f5555f046a0> is not bound to a Session; attribute refresh operation cannot proceed, but if I call db.session.commit() inside perform_action() instead of work_hard(), it works. Similarly, if I try to access flask's request instance, it works in perform_action() but not work_hard() (it complains that I'm trying to access the request outside of a request context).
I assume that these are both because work_hard() is executing after perform_action() has returned. Is is possible to somehow prolong the request context to include work_hard()? So far I've just been passing individual values from request to work_hard() and that worked to a point, but now I need to commit to the db and I'm not sure how to fix the db session here.
I can't just call db.session.commit() from perform_action(), I really do need to be able to make multiple updates in the db in real-time as the output is streaming to the HTTP client.
If this turns out not to be possible, my backup plan is to stream output from a subprocess, and then in the subprocess I'll connect to the db from there, but I'd prefer to do it all within the same process if possible.
Thanks!