Closed pdoggi closed 5 years ago
Hey pdoggi, your setup looks correct.
As a work around, maybe you could force the app context with something like this...
app = Flask(__name__) # If declared in same file, or import it
@celery.task(base=QueueOnce, once={'graceful': True})
def slow_task(id):
with app.app_context():
result = CustomORModel.query.filter_by(id=id).first()
do_something_with(result)
Could you post the full stack-trace and which version of flask this is with so I can debug this a little further?
very strange for this problem.
In the Flask documentation, they give the following example for Celery integration:
def make_celery(app):
celery = Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
In order to get QueueOnce
to properly inherit from ContextClass
instead of celery.Task
, the following snippet will work:
ContextQueueOnce = QueueOnce
ContextQueueOnce.__bases__ = (ContextTask,)
This is not recommended, but works for the current version
@mbierma Thanks for the work-around!
I'm gonna update documentation with an alternative, with a context aware QueueOnce task base. If anyone can figure out a more elegant solution, it would be welcome.
def make_celery(app):
celery = Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
class ContextQueueOnce(QueueOnce):
def __call__(self, *args, **kwargs):
with app.app_context():
return super(ContextQueueOnce, self).__call__(*args, **kwargs)
celery.Task = ContextTask
celery.QueueOnce = ContextQueueOnce
return celery
...
celery = make_celery(app)
@celery.task(base=celery.QueueOnce)
def example_task(value):
return
Gonna close this out, as it's added to the docs! If anyone figures out a more elegant way to integrate celery_once with Flask, happy to try and put that in place instead.
Thank you for the great work on this library!
Following the usage directions worked perfectly out of the box, but once I needed to lookup a record in my database, I get a
RuntimeError: Working outside of application context.
This code works
This code doesn't work
Using celery's base Task class plays nicely with my db lookup--that is, it works when I remove
base=QueueOnce, once={'graceful': True}
, but I need the task locking mechanism offered by celery-once.Anyone else have experience with this? Maybe, I'm missing something pretty basic in my setup or the way I'm calling my query.
Any help would be greatly appreciated! Thanks in advance.
Connie