Repository: getredash/redash

Issue:
Alert notifications fail (sometime) with a SQLAlchemy error
### Issue Summary

After migrating to 1.0.1 alerts are notified only sporadically to Slack (I cannot pinpoint exactly the conditions in which it happens).

### Steps to Reproduce

1. Create a failing alert for an existing query
2. Add your email and a Slack destination to your alert (the order seems to matter: add first the email destination then the slack destination)
3. Refresh the query such that the alert would trigger
4. You will receive an alert email but no slack alert
5. In the back-end `celery_error.log` you will see an error message like
```
[2017-04-18 13:13:58,184: ERROR/Worker-4] redash.tasks.check_alerts_for_query[fb4fee06-3318-44f7-8aaf-7984d792a793]: Error with processing destination
Traceback (most recent call last):
  File "/opt/redash/redash.1.0.1.b2833/redash/tasks/alerts.py", line 23, in notify_subscriptions
    subscription.notify(alert, alert.query_rel, subscription.user, new_state, current_app, host)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 237, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 584, in get
    value = self.callable_(state, passive)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/strategies.py", line 530, in _load_for_state
    (orm_util.state_str(state), self.key)
DetachedInstanceError: Parent instance <AlertSubscription at 0x7fcd934f04d0> is not bound to a Session; lazy load operation of attribute 'user' cannot proceed
```

I think this error is caused by the `subscription.user` call.
My guess is that it is eventually caused by [`models.db.session.commit()`](https://github.com/getredash/redash/blob/master/redash/tasks/alerts.py#L51). 

This "might" be connected to #1706 .

### Technical details:

* Redash Version: 1.0.1+b2833
* Browser/OS: (not relevant, error is in the backend)
* How did you install Redash: ec2 from ami (in 2015), recently upgraded from 0.12 to 1.0.1



Discussion:
But we initialize SQLAlchemy with `expire_on_commit` set to `False`:
```
db = SQLAlchemy(session_options={
    'expire_on_commit': False
})
```
([source](https://github.com/getredash/redash/blob/master/redash/models.py#L35))

It should take care of such issues :|

You provided detailed steps to reproduce, so I will try to write a test for this and see what's going on.
This is definitely still happening even after moving from an old ec2 instance to a docker based installation. 
Today I will try to narrow the bug down and reproduce it.
Also seeing this on 1.0.3+b2850 on Docker.
@danielerapati @copester Do you see it happen with the same line/same objects, as in the issue description or a different one?

Resolving patch:
diff --git a/redash/destinations/email.py b/redash/destinations/email.py
--- a/redash/destinations/email.py
+++ b/redash/destinations/email.py
@@ -40,16 +40,15 @@ def notify(self, alert, query, user, new_state, app, host, options):
         logging.debug("Notifying: %s", recipients)
 
         try:
-            with app.app_context():
-                alert_name = alert.name.encode('utf-8', 'ignore')
-                state = new_state.upper()
-                subject_template = options.get('subject_template', settings.ALERTS_DEFAULT_MAIL_SUBJECT_TEMPLATE)
-                message = Message(
-                    recipients=recipients,
-                    subject=subject_template.format(alert_name=alert_name, state=state),
-                    html=html
-                )
-                mail.send(message)
+            alert_name = alert.name.encode('utf-8', 'ignore')
+            state = new_state.upper()
+            subject_template = options.get('subject_template', settings.ALERTS_DEFAULT_MAIL_SUBJECT_TEMPLATE)
+            message = Message(
+                recipients=recipients,
+                subject=subject_template.format(alert_name=alert_name, state=state),
+                html=html
+            )
+            mail.send(message)
         except Exception:
             logging.exception("Mail send error.")
 
diff --git a/redash/tasks/general.py b/redash/tasks/general.py
--- a/redash/tasks/general.py
+++ b/redash/tasks/general.py
@@ -1,9 +1,10 @@
 import requests
+
 from celery.utils.log import get_task_logger
 from flask_mail import Message
-from redash.worker import celery
+from redash import mail, models, settings
 from redash.version_check import run_version_check
-from redash import models, mail, settings
+from redash.worker import celery
 
 logger = get_task_logger(__name__)
 
@@ -50,12 +51,11 @@ def send_mail(to, subject, html, text):
     from redash.wsgi import app
 
     try:
-        with app.app_context():
-            message = Message(recipients=to,
-                              subject=subject,
-                              html=html,
-                              body=text)
+        message = Message(recipients=to,
+                          subject=subject,
+                          html=html,
+                          body=text)
 
-            mail.send(message)
+        mail.send(message)
     except Exception:
         logger.exception('Failed sending message: %s', message.subject)


Test patch: