Repository: getredash/redash

Issue:
RuntimeError: Working outside of application context.
After deploying v6-beta to demo.redash.io we started seeing this error, which we haven't before:
https://sentry.io/share/issue/08f84c11d6d04474b642b2d1435f9fb8/

By guessing what might be the cause of the issue I commented out the following code:

https://github.com/getredash/redash/blob/cfe12c5a5d37b8ec01c8a26fd9c8c8ad97e12d07/redash/worker.py#L85-L90

Once I have the issue stopped happening. The reason I suspected this code was because we call `create_app` here for the second time during the initialization process of Celery.

I'm not sure why it causes it though or how to fix it (aside from removing this code). 🤔 

@jezdez @emtwo If I'm not mistaken, you were running this code in your env for a long time now. You haven't seen this exception?


Discussion:
Hm, I have personally not come across this and I'm having trouble reproducing it locally in the docker dev environment. Can you reproduce it locally or does this only show up on sentry?

One idea we could try in `add_periodic_tasks()` is similar to what's done here to avoid creating a new context if it's not needed:
https://github.com/getredash/redash/blob/master/redash/cli/__init__.py#L13

`app = current_app or create_app()`

I couldn't reproduce it locally, although I didn't invest much time in it. I will give the `current_app or  create_app()` option a try and see if the problem stops or persists. 

But can you check in your production's Sentry reports if there was a report of a similar error?

Resolving patch:
diff --git a/redash/__init__.py b/redash/__init__.py
--- a/redash/__init__.py
+++ b/redash/__init__.py
@@ -3,7 +3,7 @@
 import urlparse
 import urllib
 import redis
-from flask import Flask
+from flask import Flask, current_app
 from flask_sslify import SSLify
 from werkzeug.contrib.fixers import ProxyFix
 from werkzeug.routing import BaseConverter
@@ -141,3 +141,11 @@ def create_app(load_admin=True):
     chrome_logger.init_app(app)
 
     return app
+
+
+def safe_create_app():
+    """Return current_app or create a new one."""
+    if current_app:
+        return current_app
+
+    return create_app()
\ No newline at end of file
diff --git a/redash/worker.py b/redash/worker.py
--- a/redash/worker.py
+++ b/redash/worker.py
@@ -8,7 +8,7 @@
 from celery import Celery
 from celery.schedules import crontab
 from celery.signals import worker_process_init
-from redash import __version__, create_app, settings
+from redash import __version__, safe_create_app, settings
 from redash.metrics import celery as celery_metrics
 
 celery = Celery('redash',
@@ -77,14 +77,14 @@ def __call__(self, *args, **kwargs):
 # Create Flask app after forking a new worker, to make sure no resources are shared between processes.
 @worker_process_init.connect
 def init_celery_flask_app(**kwargs):
-    app = create_app()
+    app = safe_create_app()
     app.app_context().push()
 
 
 # Hook for extensions to add periodic tasks.
 @celery.on_after_configure.connect
 def add_periodic_tasks(sender, **kwargs):
-    app = create_app()
+    app = safe_create_app()
     periodic_tasks = getattr(app, 'periodic_tasks', {})
     for params in periodic_tasks.values():
         sender.add_periodic_task(**params)


Test patch: