Refactor: zabbixCache.

This commit is contained in:
Alexander Zobnin
2016-11-13 15:00:58 +03:00
parent 032927cf8f
commit 775a422c84

View File

@@ -5,7 +5,7 @@ import _ from 'lodash';
// Each datasource instance must initialize its own cache. // Each datasource instance must initialize its own cache.
/** @ngInject */ /** @ngInject */
angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $interval) { function ZabbixCachingProxyFactory($q, $interval) {
class ZabbixCachingProxy { class ZabbixCachingProxy {
constructor(zabbixAPI, ttl) { constructor(zabbixAPI, ttl) {
@@ -37,60 +37,58 @@ angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $i
$interval(_.bind(this.refresh, this), this.ttl); $interval(_.bind(this.refresh, this), this.ttl);
// Don't run duplicated history requests // Don't run duplicated history requests
this.getHistory = callHistoryOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI), this.getHistory = callAPIRequestOnce(_.bind(this.zabbixAPI.getHistory, this.zabbixAPI),
this.historyPromises); this.historyPromises, getHistoryRequestHash);
// Don't run duplicated requests // Don't run duplicated requests
this.groupPromises = {}; this.groupPromises = {};
this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI), this.getGroupsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getGroups, this.zabbixAPI),
this.groupPromises); this.groupPromises, getAPIRequestHash);
this.hostPromises = {}; this.hostPromises = {};
this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI), this.getHostsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getHosts, this.zabbixAPI),
this.hostPromises); this.hostPromises, getAPIRequestHash);
this.appPromises = {}; this.appPromises = {};
this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI), this.getAppsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getApps, this.zabbixAPI),
this.appPromises); this.appPromises, getAPIRequestHash);
this.itemPromises = {}; this.itemPromises = {};
this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI), this.getItemsOnce = callAPIRequestOnce(_.bind(this.zabbixAPI.getItems, this.zabbixAPI),
this.itemPromises); this.itemPromises, getAPIRequestHash);
} }
_refresh() { _refresh() {
var self = this; let promises = [
var promises = [
this.zabbixAPI.getGroups() this.zabbixAPI.getGroups()
]; ];
return this.$q.all(promises).then(function(results) { return Promise.all(promises)
.then(results => {
if (results.length) { if (results.length) {
self._groups = results[0]; this._groups = results[0];
} }
self._initialized = true; this._initialized = true;
}); });
} }
getGroups() { getGroups() {
var self = this;
if (this._groups) { if (this._groups) {
return this.$q.when(self._groups); return Promise.resolve(this._groups);
} else { } else {
return this.getGroupsOnce() return this.getGroupsOnce()
.then(groups => { .then(groups => {
self._groups = groups; this._groups = groups;
return self._groups; return groups;
}); });
} }
} }
getHosts(groupids) { getHosts(groupids) {
//var self = this;
return this.getHostsOnce(groupids) return this.getHostsOnce(groupids)
.then(hosts => { .then(hosts => {
// iss #196 - disable caching due performance issues // iss #196 - disable caching due performance issues
//self._hosts = _.union(self._hosts, hosts); //this._hosts = _.union(this._hosts, hosts);
return hosts; return hosts;
}); });
} }
@@ -103,11 +101,10 @@ angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $i
} }
getItems(hostids, appids, itemtype) { getItems(hostids, appids, itemtype) {
//var self = this;
return this.getItemsOnce(hostids, appids, itemtype) return this.getItemsOnce(hostids, appids, itemtype)
.then(items => { .then(items => {
// iss #196 - disable caching due performance issues // iss #196 - disable caching due performance issues
//self._items = _.union(self._items, items); //this._items = _.union(this._items, items);
return items; return items;
}); });
} }
@@ -156,61 +153,51 @@ angular.module('grafana.services').factory('ZabbixCachingProxy', function($q, $i
} }
} }
function callAPIRequestOnce(func, promiseKeeper) { return ZabbixCachingProxy;
return function() {
var hash = getAPIRequestHash(arguments);
var deferred = $q.defer();
if (!promiseKeeper[hash]) {
promiseKeeper[hash] = deferred.promise;
func.apply(this, arguments).then(function(result) {
deferred.resolve(result);
promiseKeeper[hash] = null;
});
} else {
return promiseKeeper[hash];
}
return deferred.promise;
};
} }
function callHistoryOnce(func, promiseKeeper) { angular
return function() { .module('grafana.services')
var itemids = _.map(arguments[0], 'itemid'); .factory('ZabbixCachingProxy', ZabbixCachingProxyFactory);
var stamp = itemids.join() + arguments[1] + arguments[2];
var hash = stamp.getHash();
var deferred = $q.defer();
if (!promiseKeeper[hash]) {
promiseKeeper[hash] = deferred.promise;
func.apply(this, arguments).then(function(result) {
deferred.resolve(result);
promiseKeeper[hash] = null;
});
} else {
return promiseKeeper[hash];
}
return deferred.promise;
};
}
/**
* Wrap function to prevent multiple calls
* when waiting for result.
*/
function callOnce(func, promiseKeeper) { function callOnce(func, promiseKeeper) {
return function() { return function() {
var deferred = $q.defer();
if (!promiseKeeper) { if (!promiseKeeper) {
promiseKeeper = deferred.promise; promiseKeeper = Promise.resolve(
func.apply(this, arguments).then(function(result) { func.apply(this, arguments)
deferred.resolve(result); .then(result => {
promiseKeeper = null; promiseKeeper = null;
}); return result;
} else { })
return promiseKeeper; );
} }
return deferred.promise; return promiseKeeper;
}; };
} }
return ZabbixCachingProxy; /**
}); * Wrap zabbix API request to prevent multiple calls
* with same params when waiting for result.
*/
function callAPIRequestOnce(func, promiseKeeper, argsHashFunc) {
return function() {
var hash = argsHashFunc(arguments);
if (!promiseKeeper[hash]) {
promiseKeeper[hash] = Promise.resolve(
func.apply(this, arguments)
.then(result => {
promiseKeeper[hash] = null;
return result;
})
);
}
return promiseKeeper[hash];
};
}
function getAPIRequestHash(args) { function getAPIRequestHash(args) {
var requestStamp = _.map(args, arg => { var requestStamp = _.map(args, arg => {
@@ -223,16 +210,21 @@ function getAPIRequestHash(args) {
return requestStamp.getHash(); return requestStamp.getHash();
} }
function getHistoryRequestHash(args) {
let itemids = _.map(args[0], 'itemid');
let stamp = itemids.join() + args[1] + args[2];
return stamp.getHash();
}
String.prototype.getHash = function() { String.prototype.getHash = function() {
var hash = 0, i, chr, len; var hash = 0, i, chr, len;
if (this.length === 0) { if (this.length !== 0) {
return hash;
}
for (i = 0, len = this.length; i < len; i++) { for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i); chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr; hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer hash |= 0; // Convert to 32bit integer
} }
}
return hash; return hash;
}; };