AMBARI-20253. HiveView2.0: Auto refresh not working.(dipayanb)

Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/dff7754b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/dff7754b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/dff7754b

Branch: refs/heads/branch-dev-logsearch
Commit: dff7754b7cb718de7e3bcfaac7afa0a4ce936afe
Parents: a92b7c8
Author: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Authored: Wed Mar 8 01:02:16 2017 +0530
Committer: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Committed: Wed Mar 8 01:02:16 2017 +0530

----------------------------------------------------------------------
 .../main/resources/ui/app/routes/databases.js   |  23 +++
 .../ui/app/routes/databases/database/tables.js  |  57 ++++++-
 .../app/routes/databases/database/tables/new.js |  18 ++-
 .../resources/ui/app/services/auto-refresh.js   | 148 +++++++++++++++++++
 .../app/templates/databases/database/tables.hbs |   1 +
 .../main/resources/ui/app/transforms/date.js    |  50 +++++++
 .../src/main/resources/ui/config/environment.js |   6 +-
 7 files changed, 289 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
index e5efbe9..02dbcac 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
@@ -18,9 +18,32 @@
 
 import Ember from 'ember';
 import UILoggerMixin from '../mixins/ui-logger';
+import ENV from 'ui/config/environment';
 
 export default Ember.Route.extend(UILoggerMixin, {
   tableOperations: Ember.inject.service(),
+  autoRefresh: Ember.inject.service(),
+
+  activate() {
+    if(ENV.APP.SHOULD_AUTO_REFRESH_DATABASES) {
+      this.get('autoRefresh').startDatabasesAutoRefresh(() => {
+        console.log("Databases AutoRefresh started");
+      }, this._databasesRefreshed.bind(this));
+    }
+
+  },
+
+  deactivate() {
+    this.get('autoRefresh').stopDatabasesAutoRefresh();
+  },
+
+  _databasesRefreshed() {
+    let model = this.store.peekAll('database');
+    if(this.controller) {
+      console.log(model.get('length'));
+      this.setupController(this.controller, model);
+    }
+  },
 
   model() {
     return this.store.findAll('database', {reload: true});

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables.js
 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables.js
index d4a39cb..f5940e3 100644
--- 
a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables.js
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables.js
@@ -17,8 +17,46 @@
  */
 
 import Ember from 'ember';
+import ENV from 'ui/config/environment';
+import UILoggerMixin from '../../../mixins/ui-logger';
+
+export default Ember.Route.extend(UILoggerMixin, {
+  autoRefresh: Ember.inject.service(),
+
+  activate() {
+    if(ENV.APP.SHOULD_AUTO_REFRESH_TABLES) {
+      let selectedDatabase = this.modelFor('databases.database');
+      
this.get('autoRefresh').startTablesAutoRefresh(selectedDatabase.get('name'),
+        this.tableRefreshStarting.bind(this), this.tableRefreshed.bind(this));
+    }
+  },
+
+  deactivate() {
+    
this.get('autoRefresh').stopTablesAutoRefresh(this.controller.get('database.name'));
+  },
+
+  tableRefreshStarting(databaseName) {
+    this.controller.set('tableRefreshing', true);
+  },
+
+  tableRefreshed(databaseName, deletedTablesCount) {
+    this.controller.set('tableRefreshing', false);
+    let currentTablesForDatabase = 
this.store.peekAll('table').filterBy('database.name', databaseName);
+    let paramsForTable = this.paramsFor('databases.database.tables.table');
+    let currentTableNamesForDatabase = currentTablesForDatabase.mapBy('name');
+    if (currentTableNamesForDatabase.length <= 0  || 
!currentTableNamesForDatabase.contains(paramsForTable.name)) {
+      if(deletedTablesCount !== 0) {
+        this.get('logger').info(`Current selected table 
'${paramsForTable.name}' has been deleted from Hive Server. Transitioning 
out.`);
+        this.transitionTo('databases.database', databaseName);
+        return;
+      }
+    }
+    if(currentTablesForDatabase.get('length') > 0) {
+      this.selectTable(currentTablesForDatabase);
+      this.controller.set('model', currentTablesForDatabase);
+    }
+  },
 
-export default Ember.Route.extend({
   model() {
     let selectedDatabase = this.modelFor('databases.database');
     return this.store.query('table', {databaseId: 
selectedDatabase.get('name')});
@@ -44,6 +82,13 @@ export default Ember.Route.extend({
       toSelect.set('selected', true);
     }
   },
+
+  setupController(controller, model) {
+    this._super(...arguments);
+    let selectedDatabase = this.modelFor('databases.database');
+    controller.set('database', selectedDatabase);
+  },
+
   actions: {
     tableSelected(table) {
       let tables = 
this.controllerFor('databases.database.tables').get('model');
@@ -52,11 +97,11 @@ export default Ember.Route.extend({
       });
       table.set('selected', true);
       this.transitionTo('databases.database.tables.table', table.get('name'));
+    },
+
+    refreshTable() {
+      let databaseName = this.controller.get('database.name');
+      this.get('autoRefresh').refreshTables(databaseName, 
this.tableRefreshStarting.bind(this), this.tableRefreshed.bind(this), true);
     }
   }
-
-
-
-
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js
 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js
index 533dd61..b61008f 100644
--- 
a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js
@@ -95,13 +95,17 @@ export default Ember.Route.extend(UILoggerMixin, {
   },
 
   _addTableToStoreLocally(database, table) {
-    this.store.createRecord('table', {
-      id: `${database.get('name')}/${table}`,
-      name: `${table}`,
-      type: 'TABLE',
-      selected: true,
-      database: database
-    });
+    // Add only if it has not been added by the auto refresh
+    let existingRecord = this.store.peekRecord('table', 
`${database.get('name')}/${table}`);
+    if(Ember.isEmpty(existingRecord)) {
+      this.store.createRecord('table', {
+        id: `${database.get('name')}/${table}`,
+        name: `${table}`,
+        type: 'TABLE',
+        selected: true,
+        database: database
+      });
+    }
   },
 
   _resetModelInTablesController(tables) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/services/auto-refresh.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/services/auto-refresh.js 
b/contrib/views/hive20/src/main/resources/ui/app/services/auto-refresh.js
new file mode 100644
index 0000000..2e8ec62
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/services/auto-refresh.js
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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 Ember from 'ember';
+
+export default Ember.Service.extend({
+  store: Ember.inject.service(),
+  isDatabaseRefresherRunning: false,
+  tablesRefresherRunningStatus: {},
+
+
+  startDatabasesAutoRefresh(databaseRefreshStartingCallback, 
databaseRefreshedCallback, startAfter = 30 * 1000, interval = 30 * 1000) {
+    if (this.get('isDatabaseRefresherRunning')) {
+      return;
+    }
+
+    console.log("Starting database auto refresh");
+
+    this.set('isDatabaseRefresherRunning', true);
+    Ember.run.later(() => {
+      this._refreshDatabases(databaseRefreshStartingCallback, 
databaseRefreshedCallback, interval);
+    }, startAfter);
+
+
+  },
+
+  _refreshDatabases(databaseRefreshStartingCallback, 
databaseRefreshedCallback, interval) {
+    let reRun = () => {
+      Ember.run.later(() => {
+        this._refreshDatabases(databaseRefreshStartingCallback, 
databaseRefreshedCallback, interval);
+      }, interval);
+    };
+
+    if (this.get('isDatabaseRefresherRunning')) {
+      databaseRefreshStartingCallback();
+      let oldDatabases = this.get('store').peekAll('database').mapBy('name');
+      this.get('store').query('database', {}).then((data) => {
+        let deletedDbCount = 0
+        let newDatabases = data.mapBy('name');
+        oldDatabases.forEach((oldDB) => {
+          if (!newDatabases.contains(oldDB)) {
+            deletedDbCount++;
+            let oldRecord = this.get('store').peekRecord('database', oldDB);
+            this.get('store').unloadRecord(oldRecord);
+          }
+        });
+
+        // Hack: Had to wrap the refreshed call inside run later because, 
unloadRecord is not synchronously unloading
+        // records from store.
+        Ember.run.later(() => databaseRefreshedCallback(deletedDbCount));
+        reRun();
+      }).catch((err) => {
+        reRun();
+      });
+    }
+  },
+
+  stopDatabasesAutoRefresh() {
+    console.log("Stopping database auto refresh");
+    this.set('isDatabaseRefresherRunning', false);
+  },
+
+  startTablesAutoRefresh(databaseName, tablesRefreshStartingCallback, 
tablesRefreshedCallback, startAfter = 15 * 1000, interval = 15 * 1000) {
+    if(!Ember.isEmpty(this.get('tablesRefresherRunningStatus')[databaseName])) 
{
+      if (this.get('tablesRefresherRunningStatus')[databaseName]["started"]) {
+        return;
+      }
+    }
+
+
+    console.log("Starting tables auto refresh for " + databaseName);
+
+    this.get('tablesRefresherRunningStatus')[databaseName] = {};
+    this.get('tablesRefresherRunningStatus')[databaseName]["started"] = true;
+    Ember.run.later(() => {
+      this.refreshTables(databaseName, tablesRefreshStartingCallback, 
tablesRefreshedCallback, false, interval);
+    }, startAfter);
+  },
+
+  refreshTables(databaseName, tablesRefreshStartingCallback, 
tablesRefreshedCallback, runOnce = false, interval) {
+    let reRun = () => {
+      let intervalRef = Ember.run.later(() => {
+        this.refreshTables(databaseName, tablesRefreshStartingCallback, 
tablesRefreshedCallback, false, interval);
+      }, interval);
+      this.get('tablesRefresherRunningStatus')[databaseName]["intervalRef"] = 
intervalRef;
+    };
+
+    if (this.get('tablesRefresherRunningStatus')[databaseName]) {
+      tablesRefreshStartingCallback(databaseName);
+      let oldTableNames = 
this.get('store').peekAll('table').filterBy('database.name', 
databaseName).mapBy('name');
+      this.get('store').query('table', {databaseId: databaseName}).then((data) 
=> {
+        let deletedTablesCount = 0;
+        let newTableNames = data.mapBy('name');
+        oldTableNames.forEach((oldTable) => {
+          if (!newTableNames.contains(oldTable)) {
+            deletedTablesCount++;
+            let oldRecord = this.get('store').peekRecord('table', 
`${databaseName}/${oldTable}`);
+            this.get('store').unloadRecord(oldRecord);
+          }
+        });
+
+        newTableNames.forEach((newTable) => {
+          if(!oldTableNames.contains(newTable)) {
+            //table has been added
+            let tableRecord = this.get('store').peekRecord('table', 
`${databaseName}/${newTable}`);
+            let dbRecord = this.get('store').peekRecord('database', 
databaseName);
+            dbRecord.get('tables').pushObject(tableRecord);
+          }
+        });
+
+        // Hack: Had to wrap the refreshed call inside run later because, 
unloadRecord is not synchronously unloading
+        // records from store.
+        Ember.run.later(() => tablesRefreshedCallback(databaseName, 
deletedTablesCount));
+        if(!runOnce) {
+          reRun();
+        }
+      }).catch((err) => {
+        if(!runOnce) {
+          reRun();
+        }
+      });
+    }
+  },
+
+  stopTablesAutoRefresh(databaseName) {
+    console.log("Stopping tables auto refresh for " + databaseName);
+    this.get('tablesRefresherRunningStatus')[databaseName]["started"] = false;
+    let intervalRef = 
this.get('tablesRefresherRunningStatus')[databaseName]["intervalRef"];
+    if (intervalRef) {
+      Ember.run.cancel(intervalRef);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables.hbs
 
b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables.hbs
index c2d845b..954725b 100644
--- 
a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables.hbs
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables.hbs
@@ -20,6 +20,7 @@
   <div class="col-md-3">
     <div class="row">
       <div class="hv-dropdown tables-dropdown">
+        <a href="#" {{action "refreshTable"}} class="btn 
btn-default">{{fa-icon "refresh" spin=tableRefreshing}}</a>
         {{#link-to "databases.database.tables.new" class="btn 
btn-success"}}{{fa-icon "plus"}}{{/link-to}}
       </div>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/app/transforms/date.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/transforms/date.js 
b/contrib/views/hive20/src/main/resources/ui/app/transforms/date.js
new file mode 100644
index 0000000..40804d5
--- /dev/null
+++ b/contrib/views/hive20/src/main/resources/ui/app/transforms/date.js
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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 Ember from 'ember';
+import DS from 'ember-data';
+
+export default DS.Transform.extend({
+
+  deserialize: function (serialized) {
+    var type = typeof serialized;
+
+    if (type === "string") {
+      return new Date(Ember.Date.parse(serialized));
+    } else if (type === "number") {
+      return new Date(serialized);
+    } else if (serialized === null || serialized === undefined) {
+      // if the value is not present in the data,
+      // return undefined, not null.
+      return serialized;
+    } else {
+      return null;
+    }
+  },
+
+  serialize: function (date) {
+    console.log("Coming here to serialize");
+    if (date instanceof Date) {
+      // Serialize it as a number to maintain millisecond precision
+      return Number(date);
+    } else {
+      return null;
+    }
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/dff7754b/contrib/views/hive20/src/main/resources/ui/config/environment.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/config/environment.js 
b/contrib/views/hive20/src/main/resources/ui/config/environment.js
index 411ee99..c5370d7 100644
--- a/contrib/views/hive20/src/main/resources/ui/config/environment.js
+++ b/contrib/views/hive20/src/main/resources/ui/config/environment.js
@@ -34,7 +34,9 @@ module.exports = function(environment) {
     APP: {
       // Here you can pass flags/options to your application instance
       // when it is created
-      SHOULD_PERFORM_SERVICE_CHECK: true
+      SHOULD_PERFORM_SERVICE_CHECK: true,
+      SHOULD_AUTO_REFRESH_TABLES: true,
+      SHOULD_AUTO_REFRESH_DATABASES: true
     }
   };
 
@@ -49,6 +51,8 @@ module.exports = function(environment) {
     // Change the value to false to prevent the service checks. This is 
required in development mode
     // as service checks take up time and hence increase the overall 
development time.
     ENV.APP.SHOULD_PERFORM_SERVICE_CHECK = false;
+    ENV.APP.SHOULD_AUTO_REFRESH_TABLES = false;
+    ENV.APP.SHOULD_AUTO_REFRESH_DATABASES = false;
   }
 
   if (environment === 'test') {

Reply via email to