Repository: getredash/redash

Issue:
When deleting a data source, it should remove the cached schema from Redis
When deleting a data source ([DataSource#delete](https://github.com/getredash/redash/blob/dda75cce24437d5c308b2ca8c42acaa164a62667/redash/models/__init__.py#L138-L143)), we need to remove the cached schema from Redis as well.

(The schema is being in the [DataSource#get_schema](https://github.com/getredash/redash/blob/dda75cce24437d5c308b2ca8c42acaa164a62667/redash/models/__init__.py#L145-L160) method.)


Discussion:

Resolving patch:
diff --git a/redash/models/__init__.py b/redash/models/__init__.py
--- a/redash/models/__init__.py
+++ b/redash/models/__init__.py
@@ -140,41 +140,47 @@ def delete(self):
         QueryResult.query.filter(QueryResult.data_source == self).delete()
         res = db.session.delete(self)
         db.session.commit()
+
+        redis_connection.delete(self._schema_key)
+
         return res
 
     def get_schema(self, refresh=False):
-        key = "data_source:schema:{}".format(self.id)
-
         cache = None
         if not refresh:
-            cache = redis_connection.get(key)
+            cache = redis_connection.get(self._schema_key)
 
         if cache is None:
             query_runner = self.query_runner
             schema = sorted(query_runner.get_schema(get_stats=refresh), key=lambda t: t['name'])
 
-            redis_connection.set(key, json_dumps(schema))
+            redis_connection.set(self._schema_key, json_dumps(schema))
         else:
             schema = json_loads(cache)
 
         return schema
 
+    @property
+    def _schema_key(self):
+        return "data_source:schema:{}".format(self.id)
+
+    @property
     def _pause_key(self):
         return 'ds:{}:pause'.format(self.id)
 
     @property
     def paused(self):
-        return redis_connection.exists(self._pause_key())
+        return redis_connection.exists(self._pause_key)
 
     @property
     def pause_reason(self):
-        return redis_connection.get(self._pause_key())
+        return redis_connection.get(self._pause_key)
 
     def pause(self, reason=None):
-        redis_connection.set(self._pause_key(), reason or '')
+        redis_connection.set(self._pause_key, reason or '')
 
     def resume(self):
-        redis_connection.delete(self._pause_key())
+        redis_connection.delete(self._pause_key)
 
     def add_group(self, group, view_only=False):
         dsg = DataSourceGroup(group=group, data_source=self, view_only=view_only)


Test patch:
diff --git a/tests/models/test_data_sources.py b/tests/models/test_data_sources.py
--- a/tests/models/test_data_sources.py
+++ b/tests/models/test_data_sources.py
@@ -1,4 +1,5 @@
 import mock
+from mock import patch
 from tests import BaseTestCase
 
 from redash.models import DataSource, Query, QueryResult
@@ -96,3 +97,10 @@ def test_deletes_child_models(self):
         data_source.delete()
         self.assertIsNone(DataSource.query.get(data_source.id))
         self.assertEqual(0, QueryResult.query.filter(QueryResult.data_source == data_source).count())
+
+    @patch('redash.redis_connection.delete')
+    def test_deletes_schema(self, mock_redis):
+        data_source = self.factory.create_data_source()
+        data_source.delete()
+
+        mock_redis.assert_called_with(data_source._schema_key)