Reputation: 59
I have a Flask application that is using the factory function pattern (from the intro tutorial) and am attempting to offload a long running job to a background worker with a Redis queue. I am invoking the background work from a Blueprint, and am unable to pass the application context along with the invocation. The intention is to use the application context and the SQLite configuration to perform writes to it from the background thread. What am I missing here? I think this may be more of a "you just don't know enough about how Flask works" issue and if that is the case, please let me know what I'm doing wrong! Thanks.
ERROR
RuntimeError: Working outside of application context.
dy.py
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
Blueprint module:
from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for, Response, current_app
)
import sqlite3
from app.db import get_db
from rq import Queue
from redis import Redis
bp = Blueprint('perform_work', __name__)
q = Queue(connection=Redis())
def some_func():
db = get_db()
...
def generate_work():
result = q.enqueue(some_func)
...
@bp.route('/perform_work', methods=['POST'])
def perform_work():
...
generate_work()
worker.py
import os
import redis
from rq import Worker, Queue, Connection
listen = ['default']
redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')
conn = redis.from_url(redis_url)
if __name__ == '__main__':
with Connection(conn):
worker = Worker(list(map(Queue, listen)))
worker.work()
Upvotes: 0
Views: 674
Reputation: 59
alright well im glad i typed this out i guess. the context of the app was never registered with the worker, which should've occurred in worker.py, so yeah the worker had no idea about the application itself. here's the updated worker.py that registers the app's context:
import os
import redis
from rq import Worker, Queue, Connection
from app import create_app
listen = ['default']
redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')
conn = redis.from_url(redis_url)
app = create_app()
app.app_context().push()
if __name__ == '__main__':
with Connection(conn):
worker = Worker(list(map(Queue, listen)))
worker.work()
Upvotes: 1