瀏覽代碼

HUE-8758 [connectors] Switch to synchronized initial hueConfig

The config is always fetched before the page is rendered so there's always a last known config
Johan Ahlen 5 年之前
父節點
當前提交
4edcb07bdb

+ 36 - 45
desktop/core/src/desktop/js/apps/notebook/editorViewModel.js

@@ -52,9 +52,7 @@ class EditorViewModel {
 
     const updateConnector = type => {
       if (type) {
-        findConnector(connector => connector.type === type).then(connector => {
-          self.activeConnector(connector);
-        });
+        self.activeConnector(findConnector(connector => connector.type === type));
       }
     };
 
@@ -610,52 +608,45 @@ class EditorViewModel {
     self.newNotebook = function(editorType, callback, queryTab) {
       const type = editorType || options.editor_type;
 
-      const create = () => {
-        $.post(
-          '/notebook/api/create_notebook',
-          {
-            type: type,
-            directory_uuid: window.location.getParameter('directory_uuid'),
-            gist: self.isNotificationManager() ? undefined : window.location.getParameter('gist')
-          },
-          data => {
-            self.loadNotebook(data.notebook);
-            if (self.editorMode() && !self.isNotificationManager()) {
-              const snippet =
-                self.selectedNotebook().snippets().length == 0
-                  ? self.selectedNotebook().newSnippet(self.editorType())
-                  : self.selectedNotebook().snippets()[0];
-              if (
-                queryTab &&
-                ['queryHistory', 'savedQueries', 'queryBuilderTab'].indexOf(queryTab) > -1
-              ) {
-                snippet.currentQueryTab(queryTab);
-              }
-              huePubSub.publish('detach.scrolls', self.selectedNotebook().snippets()[0]);
-              if (window.location.getParameter('type') === '') {
-                hueUtils.changeURLParameter('type', self.editorType());
-              }
-              if (!self.isNotificationManager()) {
-                huePubSub.publish(ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT, self.activeConnector());
-              }
-            }
+      if (!self.isNotificationManager()) {
+        self.activeConnector(findConnector(connector => connector.type === type));
+        huePubSub.publish(ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT, self.activeConnector());
+      }
 
-            if (callback) {
-              callback();
+      $.post(
+        '/notebook/api/create_notebook',
+        {
+          type: type,
+          directory_uuid: window.location.getParameter('directory_uuid'),
+          gist: self.isNotificationManager() ? undefined : window.location.getParameter('gist')
+        },
+        data => {
+          self.loadNotebook(data.notebook);
+          if (self.editorMode() && !self.isNotificationManager()) {
+            const snippet =
+              self.selectedNotebook().snippets().length === 0
+                ? self.selectedNotebook().newSnippet(self.editorType())
+                : self.selectedNotebook().snippets()[0];
+            if (
+              queryTab &&
+              ['queryHistory', 'savedQueries', 'queryBuilderTab'].indexOf(queryTab) > -1
+            ) {
+              snippet.currentQueryTab(queryTab);
+            }
+            huePubSub.publish('detach.scrolls', self.selectedNotebook().snippets()[0]);
+            if (window.location.getParameter('type') === '') {
+              hueUtils.changeURLParameter('type', self.editorType());
+            }
+            if (!self.isNotificationManager()) {
+              huePubSub.publish(ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT, self.activeConnector());
             }
           }
-        );
-      };
 
-      if (!self.isNotificationManager()) {
-        findConnector(connector => connector.type === type).then(connector => {
-          self.activeConnector(connector);
-          huePubSub.publish(ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT, self.activeConnector());
-          create();
-        });
-      } else {
-        create();
-      }
+          if (callback) {
+            callback();
+          }
+        }
+      );
     };
 
     self.saveNotebook = function() {

+ 1 - 1
desktop/core/src/desktop/js/apps/notebook/snippet.js

@@ -187,7 +187,7 @@ class Snippet {
 
     const updateConnector = type => {
       if (type) {
-        findConnector(connector => connector.type === type).then(self.connector);
+        self.connector(findConnector(connector => connector.type === type));
       }
     };
 

+ 1 - 1
desktop/core/src/desktop/js/apps/notebook2/editorViewModel.js

@@ -312,7 +312,7 @@ class EditorViewModel {
   }
 
   async newNotebook(editorType, callback, queryTab) {
-    const connector = await findConnector(connector => connector.type === editorType);
+    const connector = findConnector(connector => connector.type === editorType);
     if (!connector) {
       console.warn('No connector found for type ' + editorType);
     } else {

+ 2 - 2
desktop/core/src/desktop/js/apps/notebook2/snippet.js

@@ -1042,8 +1042,8 @@ export default class Snippet {
     huePubSub.publish(REFRESH_STATEMENT_LOCATIONS_EVENT, this);
   }
 
-  async changeDialect(dialect) {
-    const connector = await findConnector(connector => connector.dialect === dialect);
+  changeDialect(dialect) {
+    const connector = findConnector(connector => connector.dialect === dialect);
     if (!connector) {
       throw new Error('No connector found for dialect ' + dialect);
     }

+ 17 - 21
desktop/core/src/desktop/js/apps/table_browser/metastoreSource.js

@@ -26,7 +26,7 @@ import {
   ASSIST_IS_DB_PANEL_READY_EVENT,
   ASSIST_SET_DATABASE_EVENT
 } from 'ko/components/assist/events';
-import { findConnector } from '../../utils/hueConfig';
+import { findConnector } from 'utils/hueConfig';
 
 class MetastoreSource {
   constructor(options) {
@@ -59,31 +59,27 @@ class MetastoreSource {
       }
     };
 
-    this.connector = ko.observable();
+    this.connector = ko.observable(findConnector(connector => connector.type === this.type));
 
-    findConnector(connector => connector.type === this.type).then(connector => {
-      this.connector(connector);
-
-      huePubSub.subscribe(ASSIST_DB_PANEL_IS_READY_EVENT, () => {
-        this.lastLoadNamespacesDeferred.done(() => {
-          let lastSelectedDb = apiHelper.getFromTotalStorage(
-            'assist_' + this.type + '_' + this.namespace.id,
-            'lastSelectedDb'
-          );
-          if (!lastSelectedDb && lastSelectedDb !== '') {
-            lastSelectedDb = 'default';
-          }
-          huePubSub.publish(ASSIST_SET_DATABASE_EVENT, {
-            connector: connector,
-            namespace: this.namespace().namespace,
-            name: lastSelectedDb
-          });
+    huePubSub.subscribe(ASSIST_DB_PANEL_IS_READY_EVENT, () => {
+      this.lastLoadNamespacesDeferred.done(() => {
+        let lastSelectedDb = apiHelper.getFromTotalStorage(
+          'assist_' + this.type + '_' + this.namespace.id,
+          'lastSelectedDb'
+        );
+        if (!lastSelectedDb && lastSelectedDb !== '') {
+          lastSelectedDb = 'default';
+        }
+        huePubSub.publish(ASSIST_SET_DATABASE_EVENT, {
+          connector: this.connector(),
+          namespace: this.namespace().namespace,
+          name: lastSelectedDb
         });
       });
-
-      huePubSub.publish(ASSIST_IS_DB_PANEL_READY_EVENT);
     });
 
+    huePubSub.publish(ASSIST_IS_DB_PANEL_READY_EVENT);
+
     const getCurrentState = () => {
       const result = {
         namespaceId: null,

+ 45 - 53
desktop/core/src/desktop/js/ko/components/assist/ko.assistDbPanel.js

@@ -23,7 +23,7 @@ import componentUtils from 'ko/components/componentUtils';
 import dataCatalog from 'catalog/dataCatalog';
 import huePubSub from 'utils/huePubSub';
 import I18n from 'utils/i18n';
-import { CONFIG_REFRESHED_EVENT, filterConnectors, GET_KNOWN_CONFIG_EVENT } from 'utils/hueConfig';
+import { CONFIG_REFRESHED_EVENT, filterConnectors } from 'utils/hueConfig';
 import {
   ASSIST_DB_HIGHLIGHT_EVENT,
   ASSIST_DB_PANEL_IS_READY_EVENT,
@@ -732,12 +732,11 @@ class AssistDbPanel {
       });
     }
 
-    this.init(options.navigationSettings).then(() => {
-      huePubSub.publish(ASSIST_DB_PANEL_IS_READY_EVENT);
+    this.init(options.navigationSettings);
+    huePubSub.publish(ASSIST_DB_PANEL_IS_READY_EVENT);
 
-      huePubSub.subscribe(ASSIST_IS_DB_PANEL_READY_EVENT, () => {
-        huePubSub.publish(ASSIST_DB_PANEL_IS_READY_EVENT);
-      });
+    huePubSub.subscribe(ASSIST_IS_DB_PANEL_READY_EVENT, () => {
+      huePubSub.publish(ASSIST_DB_PANEL_IS_READY_EVENT);
     });
   }
 
@@ -822,58 +821,51 @@ class AssistDbPanel {
     });
   }
 
-  async init(navigationSettings) {
-    return new Promise(resolve => {
-      if (this.isSolr) {
-        this.setSingleSource('solr', navigationSettings, true);
-        resolve();
-        return;
-      }
+  init(navigationSettings) {
+    if (this.isSolr) {
+      this.setSingleSource('solr', navigationSettings, true);
+      return;
+    }
 
-      if (this.isStreams) {
-        this.setSingleSource('kafka', navigationSettings, true);
-        resolve();
-        return;
-      }
+    if (this.isStreams) {
+      this.setSingleSource('kafka', navigationSettings, true);
+      return;
+    }
 
-      const updateFromConfig = async config => {
-        const sources = [];
-        const connectors = await filterConnectors(connector => connector.is_sql);
-        connectors.forEach(connector => {
-          const source =
-            this.sourceIndex[connector.type] ||
-            new AssistDbSource({
-              i18n: this.i18n,
-              type: connector.type, // TODO: Remove redundant
-              name: connector.name, // TODO: Remove redundant
-              connector: connector,
-              nonSqlType: false,
-              navigationSettings: navigationSettings
-            });
-          sources.push(source);
-        });
-        this.sourceIndex = {};
-        sources.forEach(source => {
-          this.sourceIndex[source.sourceType] = source;
-        });
+    const updateFromConfig = () => {
+      const sources = [];
+      const connectors = filterConnectors(connector => connector.is_sql);
+      connectors.forEach(connector => {
+        const source =
+          this.sourceIndex[connector.type] ||
+          new AssistDbSource({
+            i18n: this.i18n,
+            type: connector.type, // TODO: Remove redundant
+            name: connector.name, // TODO: Remove redundant
+            connector: connector,
+            nonSqlType: false,
+            navigationSettings: navigationSettings
+          });
+        sources.push(source);
+      });
+      this.sourceIndex = {};
+      sources.forEach(source => {
+        this.sourceIndex[source.sourceType] = source;
+      });
 
-        if (sources.indexOf(this.selectedSource()) === -1) {
-          if (sources.length) {
-            const storageSourceType = apiHelper.getFromTotalStorage('assist', 'lastSelectedSource');
-            this.selectedSource(this.sourceIndex[storageSourceType] || sources[0]);
-          } else {
-            this.selectedSource(undefined);
-          }
+      if (sources.indexOf(this.selectedSource()) === -1) {
+        if (sources.length) {
+          const storageSourceType = apiHelper.getFromTotalStorage('assist', 'lastSelectedSource');
+          this.selectedSource(this.sourceIndex[storageSourceType] || sources[0]);
+        } else {
+          this.selectedSource(undefined);
         }
-        this.sources(sources);
-      };
+      }
+      this.sources(sources);
+    };
 
-      huePubSub.subscribe(CONFIG_REFRESHED_EVENT, updateFromConfig);
-      huePubSub.publish(GET_KNOWN_CONFIG_EVENT, config => {
-        updateFromConfig(config);
-        resolve();
-      });
-    });
+    huePubSub.subscribe(CONFIG_REFRESHED_EVENT, updateFromConfig);
+    updateFromConfig();
   }
 }
 

+ 3 - 3
desktop/core/src/desktop/js/ko/components/assist/ko.assistFunctionsPanel.js

@@ -177,14 +177,14 @@ class AssistFunctionsPanel {
       }
     });
 
-    const configUpdated = async () => {
+    const configUpdated = () => {
       const lastActiveDialect =
         this.activeDialect() ||
         apiHelper.getFromTotalStorage('assist', 'function.panel.active.dialect');
 
       const uniqueDialects = {};
 
-      const configuredDialects = (await filterConnectors(connector => {
+      const configuredDialects = filterConnectors(connector => {
         const isMatch =
           !uniqueDialects[connector.dialect] &&
           (connector.dialect === 'hive' ||
@@ -192,7 +192,7 @@ class AssistFunctionsPanel {
             connector.dialect === 'pig');
         uniqueDialects[connector.dialect] = true;
         return isMatch;
-      })).map(connector => connector.dialect);
+      }).map(connector => connector.dialect);
       configuredDialects.sort();
       this.availableDialects(configuredDialects);
 

+ 5 - 5
desktop/core/src/desktop/js/ko/components/assist/ko.assistLangRefPanel.js

@@ -20,7 +20,7 @@ import * as ko from 'knockout';
 import componentUtils from 'ko/components/componentUtils';
 import huePubSub from 'utils/huePubSub';
 import I18n from 'utils/i18n';
-import { GET_KNOWN_CONFIG_EVENT, CONFIG_REFRESHED_EVENT, filterConnectors } from 'utils/hueConfig';
+import { CONFIG_REFRESHED_EVENT, filterConnectors } from 'utils/hueConfig';
 import { simpleGet } from 'api/apiUtils';
 import { ASSIST_LANG_REF_PANEL_SHOW_TOPIC_EVENT } from './events';
 
@@ -155,12 +155,12 @@ class AssistLangRefPanel {
       }
     });
 
-    const configUpdated = async () => {
+    const configUpdated = () => {
       const lastActiveDialect = this.activeDialect();
 
-      const configuredDialects = (await filterConnectors(
+      const configuredDialects = filterConnectors(
         connector => connector.dialect === 'hive' || connector.dialect === 'impala'
-      )).map(connector => connector.dialect);
+      ).map(connector => connector.dialect);
       configuredDialects.sort();
       this.availableDialects(configuredDialects);
 
@@ -176,7 +176,7 @@ class AssistLangRefPanel {
       }
     };
 
-    huePubSub.publish(GET_KNOWN_CONFIG_EVENT, configUpdated);
+    configUpdated();
     huePubSub.subscribe(CONFIG_REFRESHED_EVENT, configUpdated);
 
     if (this.connector()) {

+ 55 - 62
desktop/core/src/desktop/js/ko/components/contextPopover/ko.quickQueryContext.js

@@ -27,78 +27,74 @@ import DisposableComponent from 'ko/components/DisposableComponent';
 import Executor from 'apps/notebook2/execution/executor';
 import SqlExecutable from 'apps/notebook2/execution/sqlExecutable';
 import sqlStatementsParser from 'parse/sqlStatementsParser';
-import { CONFIG_REFRESHED_EVENT, filterConnectors, GET_KNOWN_CONFIG_EVENT } from 'utils/hueConfig';
-import huePubSub from 'utils/huePubSub';
+import { CONFIG_REFRESHED_EVENT, filterConnectors } from 'utils/hueConfig';
 
 export const NAME = 'quick-query-context';
 
 // prettier-ignore
 const TEMPLATE = `
 <div class="context-popover-flex-fill" style="overflow: auto;">
-  <!-- ko hueSpinner: { spin: loadingConfig, center: true, size: 'xlarge' } --><!-- /ko -->
-  <!-- ko ifnot: loadingConfig -->
-    <div style="display: inline-block" data-bind="
+  <div style="display: inline-block" data-bind="
+    component: {
+      name: '${ DROP_DOWN }',
+      params: {
+        value: interpreter,
+        labelAttribute: 'displayName',
+        entries: availableInterpreters,
+        linkTitle: 'Active connector'
+      }
+    }
+  "></div>
+  <!-- ko if: interpreter() -->
+    <div class="margin-left-10" style="display: inline-block" data-bind="
       component: {
-        name: '${ DROP_DOWN }',
+        name: '${ CONTEXT_SELECTOR }',
         params: {
-          value: interpreter,
-          labelAttribute: 'displayName',
-          entries: availableInterpreters,
-          linkTitle: 'Active connector'
+          sourceType: interpreter().type,
+          compute: compute,
+          namespace: namespace,
+          availableDatabases: availableDatabases,
+          database: database,
+          hideLabels: true
         }
       }
     "></div>
-    <!-- ko if: interpreter() -->
-      <div class="margin-left-10" style="display: inline-block" data-bind="
+  <!-- /ko -->
+  <!-- ko ifnot: loadingContext -->
+    <!-- ko with: interpreter -->
+      <div style="margin: 10px;" data-bind="
         component: {
-          name: '${ CONTEXT_SELECTOR }',
+          name: '${ SIMPLE_ACE_MULTI }',
           params: {
-            sourceType: interpreter().type,
-            compute: compute,
-            namespace: namespace,
-            availableDatabases: availableDatabases,
-            database: database,
-            hideLabels: true
+            autocomplete: $parent.autocomplete,
+            value: $parent.statement,
+            lines: 3,
+            aceOptions: {
+              minLines: 3,
+              maxLines: 5
+            },
+            mode: dialect,
+            database: $parent.database,
+            availableDatabases: $parent.availableDatabases,
+            namespace: $parent.namespace,
+            compute: $parent.compute,
+            executor: $parent.executor,
+            activeExecutable: $parent.activeExecutable
           }
         }
       "></div>
-    <!-- /ko -->
-    <!-- ko ifnot: loadingContext -->
-      <!-- ko with: interpreter -->
-        <div style="margin: 10px;" data-bind="
-          component: {
-            name: '${ SIMPLE_ACE_MULTI }',
-            params: {
-              autocomplete: $parent.autocomplete,
-              value: $parent.statement,
-              lines: 3,
-              aceOptions: {
-                minLines: 3,
-                maxLines: 5
-              },
-              mode: dialect,
-              database: $parent.database,
-              availableDatabases: $parent.availableDatabases,
-              namespace: $parent.namespace,
-              compute: $parent.compute,
-              executor: $parent.executor,
-              activeExecutable: $parent.activeExecutable
-            }
-          }
-        "></div>
-        <div data-bind="
-          component: {
-            name: '${ EXECUTABLE_ACTIONS }',
-            params: { activeExecutable: $parent.activeExecutable }
-          }
-        "></div>
-        <div data-bind="
-          component: {
-            name: '${ SIMPLE_RESULT_GRID }',
-            params: { activeExecutable: $parent.activeExecutable }
-          }
-        "></div>
-      <!-- /ko -->
+      <div data-bind="
+        component: {
+          name: '${ EXECUTABLE_ACTIONS }',
+          params: { activeExecutable: $parent.activeExecutable }
+        }
+      "></div>
+      <div data-bind="
+        component: {
+          name: '${ SIMPLE_RESULT_GRID }',
+          params: { activeExecutable: $parent.activeExecutable }
+        }
+      "></div>
     <!-- /ko -->
   <!-- /ko -->
 </div>
@@ -120,8 +116,6 @@ class QuickQueryContext extends DisposableComponent {
     this.namespace = ko.observable();
     this.compute = ko.observable();
 
-    this.loadingConfig = ko.observable(true);
-
     this.statement = ko.observable();
 
     this.loadingContext = ko.pureComputed(
@@ -143,8 +137,8 @@ class QuickQueryContext extends DisposableComponent {
       () => this.interpreter() && { type: this.interpreter().dialect }
     );
 
+    this.updateFromConfig();
     this.subscribe(CONFIG_REFRESHED_EVENT, this.updateFromConfig.bind(this));
-    huePubSub.publish(GET_KNOWN_CONFIG_EVENT, this.updateFromConfig.bind(this));
 
     let refreshExecutableThrottle = -1;
     const refreshExecutable = () => {
@@ -166,8 +160,8 @@ class QuickQueryContext extends DisposableComponent {
     this.subscribe(this.database, refreshExecutable);
   }
 
-  async updateFromConfig() {
-    const configuredSqlConnectors = await filterConnectors(connector => connector.is_sql);
+  updateFromConfig() {
+    const configuredSqlConnectors = filterConnectors(connector => connector.is_sql);
     this.availableInterpreters(configuredSqlConnectors);
 
     const found =
@@ -183,7 +177,6 @@ class QuickQueryContext extends DisposableComponent {
         this.availableInterpreters().length ? this.availableInterpreters()[0] : undefined
       );
     }
-    this.loadingConfig(false);
   }
 }
 

+ 3 - 3
desktop/core/src/desktop/js/topNavViewModel.js

@@ -38,19 +38,19 @@ class TopNavViewModel {
     self.hasJobBrowser = ko.observable(window.HAS_JOB_BROWSER);
     self.clusters = ko.observableArray();
 
-    const configUpdated = async config => {
+    const configUpdated = config => {
       if (config && config.clusters) {
         self.clusters(config.clusters);
       }
 
       self.hasJobBrowser(
         window.HAS_JOB_BROWSER &&
-          (await findConnector(
+          findConnector(
             connector =>
               connector.dialect === 'yarn' ||
               connector.dialect === 'impala' ||
               connector.dialect === 'dataeng'
-          ))
+          )
       );
     };
 

+ 18 - 12
desktop/core/src/desktop/js/utils/hueConfig.js

@@ -23,6 +23,7 @@ export const CONFIG_REFRESHED_EVENT = 'cluster.config.set.config';
 export const GET_KNOWN_CONFIG_EVENT = 'cluster.config.get.config';
 
 let lastConfigPromise = undefined;
+let lastKnownConfig = undefined;
 
 export const refreshConfig = async () => {
   lastConfigPromise = new Promise((resolve, reject) => {
@@ -30,6 +31,7 @@ export const refreshConfig = async () => {
       .getClusterConfig()
       .done(data => {
         if (data.status === 0) {
+          lastKnownConfig = data;
           resolve(data);
         } else {
           $(document).trigger('error', data.message);
@@ -50,33 +52,37 @@ export const refreshConfig = async () => {
   return lastConfigPromise;
 };
 
-const validateConfigForConnectors = config => {
+const validConnectorConfig = config => {
   if (
     !config ||
     !config.app_config ||
     !config.app_config.editor ||
     !config.app_config.editor.interpreters
   ) {
-    throw new Error('No "interpreters" attribute present in the config.');
+    console.error('No "interpreters" attribute present in the config.');
+    return false;
   }
+  return true;
 };
 
-export const findConnector = async connectorTest => {
-  const config = await lastConfigPromise;
-  validateConfigForConnectors(config);
-  const connectors = config.app_config.editor.interpreters;
-  return connectors.find(connectorTest);
+export const findConnector = connectorTest => {
+  if (validConnectorConfig(lastKnownConfig)) {
+    const connectors = lastKnownConfig.app_config.editor.interpreters;
+    return connectors.find(connectorTest);
+  }
 };
 
-export const filterConnectors = async connectorTest => {
-  const config = await lastConfigPromise;
-  validateConfigForConnectors(config);
-  const connectors = config.app_config.editor.interpreters;
-  return connectors.filter(connectorTest);
+export const filterConnectors = connectorTest => {
+  if (validConnectorConfig(lastKnownConfig)) {
+    const connectors = lastKnownConfig.app_config.editor.interpreters;
+    return connectors.filter(connectorTest);
+  }
+  return [];
 };
 
 huePubSub.subscribe(REFRESH_CONFIG_EVENT, refreshConfig);
 
+// TODO: Replace GET_KNOWN_CONFIG_EVENT pubSub with sync getKnownConfig const
 huePubSub.subscribe(GET_KNOWN_CONFIG_EVENT, callback => {
   if (lastConfigPromise && callback) {
     lastConfigPromise.then(callback).catch(callback);