Jelajahi Sumber

HUE-9275 [editor] Silence end user autocomplete calls that timeout

Romain 5 tahun lalu
induk
melakukan
cbbbf639bb

+ 66 - 0
apps/beeswax/src/beeswax/api_tests.py

@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+import logging
+import sys
+
+from nose.plugins.skip import SkipTest
+from nose.tools import assert_equal, assert_true, assert_raises
+from requests.exceptions import ReadTimeout
+
+from desktop.lib.django_test_util import make_logged_in_client
+from desktop.lib.test_utils import add_to_group, grant_access
+from useradmin.models import User
+
+from beeswax.api import _autocomplete
+
+
+if sys.version_info[0] > 2:
+  from unittest.mock import patch, Mock
+else:
+  from mock import patch, Mock
+
+
+LOG = logging.getLogger(__name__)
+
+
+class TestApi():
+
+  def setUp(self):
+    self.client = make_logged_in_client(username="test", groupname="default", recreate=True, is_superuser=False)
+    self.user = User.objects.get(username="test")
+
+  def test_autocomplete_time_out(self):
+
+    get_tables_meta=Mock(
+      side_effect=ReadTimeout("HTTPSConnectionPool(host='gethue.com', port=10001): Read timed out. (read timeout=120)")
+    )
+    db = Mock(
+      get_tables_meta=get_tables_meta
+    )
+
+    resp = _autocomplete(db, database='database')
+
+    assert_equal(
+      resp,
+      {
+        'code': 500,
+        'error': "HTTPSConnectionPool(host='gethue.com', port=10001): Read timed out. (read timeout=120)"
+      }
+    )

+ 23 - 3
desktop/libs/notebook/src/notebook/api_tests.py

@@ -42,15 +42,15 @@ from useradmin.models import User
 import notebook.connectors.hiveserver2
 
 from notebook.api import _historify
-from notebook.connectors.base import Notebook, QueryError, Api
+from notebook.connectors.base import Notebook, QueryError, Api, QueryExpired
 from notebook.decorators import api_error_handler
 from notebook.conf import get_ordered_interpreters, INTERPRETERS_SHOWN_ON_WHEEL, INTERPRETERS
 from notebook.models import Analytics
 
 if sys.version_info[0] > 2:
-  from unittest.mock import patch
+  from unittest.mock import patch, Mock
 else:
-  from mock import patch
+  from mock import patch, Mock
 
 
 class TestApi(object):
@@ -324,6 +324,26 @@ FROM déclenché c, c.addresses a"""
     assert_equal(1, data['status'])
 
 
+  def test_notebook_autocomplete(self):
+
+    with patch('notebook.api.get_api') as get_api:
+      get_api.return_value = Mock(
+        autocomplete=Mock(
+          side_effect=QueryExpired("HTTPSConnectionPool(host='gethue.com', port=10001): Read timed out. (read timeout=120)")
+        )
+      )
+
+      response = self.client.post(
+          reverse('notebook:api_autocomplete_tables', kwargs={'database': 'database'}),
+          {
+            'snippet': json.dumps({'type': 'hive'})
+          }
+      )
+
+      data = json.loads(response.content)
+      assert_equal(data, {'status': 0})  # We get back empty instead of failure with QueryExpired to silence end user messages
+
+
 class MockedApi(Api):
   def execute(self, notebook, snippet):
     return {

+ 8 - 1
desktop/libs/notebook/src/notebook/connectors/hiveserver2.py

@@ -529,7 +529,14 @@ class HS2Api(Api):
       query = self._get_current_statement(notebook, snippet)['statement']
       database, table = '', ''
 
-    return _autocomplete(db, database, table, column, nested, query=query, cluster=self.interpreter)
+    resp = _autocomplete(db, database, table, column, nested, query=query, cluster=self.interpreter)
+
+    if resp.get('error'):
+      resp['message'] = resp.pop('error')
+      if 'Read timed out' in resp['message']:
+        raise QueryExpired(resp['message'])
+
+    return resp
 
 
   @query_error_handler

+ 21 - 1
desktop/libs/notebook/src/notebook/connectors/hiveserver2_tests.py

@@ -41,7 +41,7 @@ from hadoop.pseudo_hdfs4 import is_live_cluster
 from useradmin.models import User
 
 from notebook.api import _save_notebook
-from notebook.connectors.base import QueryError
+from notebook.connectors.base import QueryError, QueryExpired
 from notebook.connectors.hiveserver2 import HS2Api
 from notebook.models import make_notebook, Notebook
 
@@ -350,6 +350,26 @@ class TestApi():
                 )
 
 
+  def test_autocomplete_time_out(self):
+    snippet = {'type': 'hive', 'properties': {}}
+
+    with patch('notebook.connectors.hiveserver2._autocomplete') as _autocomplete:
+
+      _autocomplete.return_value = {
+        'code': 500,
+        'error': "HTTPSConnectionPool(host='gethue.com', port=10001): Read timed out. (read timeout=120)"
+      }
+
+      api = HS2Api(self.user)
+
+      try:
+        resp = api.autocomplete(snippet, database='database')
+        assert_false(True)
+      except QueryExpired as e:
+        assert_equal(e.message, "HTTPSConnectionPool(host='gethue.com', port=10001): Read timed out. (read timeout=120)")
+
+
+
 class TestHiveserver2ApiNonMock(object):
 
   def setUp(self):

+ 1 - 1
desktop/libs/notebook/src/notebook/decorators.py

@@ -141,7 +141,7 @@ def api_error_handler(f):
           response['help'] = {
             'setting': {
               'name': 'max_row_size',
-              'value':str(int(_closest_power_of_2(_to_size_in_bytes(size.group(1), size.group(2)))))
+              'value': str(int(_closest_power_of_2(_to_size_in_bytes(size.group(1), size.group(2)))))
             }
           }
       if e.handle: