endpointjs
Version:
Endpoint.js enables modules within a web application to discover and use each other, whether that be on the same web page, other browser windows and tabs, iframes, servers and web workers in a reactive way by providing robust discovery, execution and stre
149 lines (137 loc) • 4.11 kB
JavaScript
/*
* (C) 2016
* Booz Allen Hamilton, All rights reserved
* Powered by InnoVision, created by the GIAT
*
* Endpoint.js was developed at the
* National Geospatial-Intelligence Agency (NGA) in collaboration with
* Booz Allen Hamilton [http://www.boozallen.com]. The government has
* "unlimited rights" and is releasing this software to increase the
* impact of government investments by providing developers with the
* opportunity to take things in new directions.
*
* Licensed 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.
*/
/* jshint -W097 */
'use strict';
var periodicTimer = require('./periodic-timer'),
inherits = require('util').inherits,
EventEmitter = require('events').EventEmitter;
inherits(ExpirableHash, EventEmitter);
module.exports = ExpirableHash;
/**
* A Javascript Hash object where the objects expire after a certain amount of
* time in milliseconds
* @constructor
*/
function ExpirableHash(duration, name) {
if (!(this instanceof ExpirableHash)) { return new ExpirableHash(duration, name); }
EventEmitter.call(this);
this._duration = duration * 1000;
this._items = 0;
this._itemsArray = [];
this._itemsHash = {};
this._timer = periodicTimer(name || 'Expirable Hash', this._duration);
this._timer.on('period', this._check.bind(this));
}
/**
* Add a key to the dictionary
* @param key
* @param value
*/
ExpirableHash.prototype.add = function(key, value) {
this._clean();
this.remove(key);
var item = {
k: key,
v: value,
t: (new Date()).getTime() + this._duration
};
this._items += 1;
this._itemsArray.push(item);
this._itemsHash[key] = item;
this._timer.addReference();
};
/**
* Get a key from the dictionary.
* @param key
*/
ExpirableHash.prototype.get = function(key) {
// Check for expired keys
this._check();
var item = this._itemsHash[key];
if (item) {
return item.v;
}
};
/**
* Update the time value of the given key
* @param key
*/
ExpirableHash.prototype.touch = function(key) {
var val = this.get(key);
if (val) {
this.remove(key);
this.add(key, val);
}
};
/**
* Remove a key from the dictionary
* @param key
*/
ExpirableHash.prototype.remove = function(key) {
var item = this._itemsHash[key];
if (item) {
this._items -= 1;
item.v = item.k = null;
item.t = 0;
delete this._itemsHash[key];
this._timer.removeReference();
}
};
/**
* Remove expired keys
* @private
*/
ExpirableHash.prototype._check = function() {
var now = (new Date()).getTime();
while (this._itemsArray.length > 0) {
var item = this._itemsArray[0];
if (item.t > now) {
break;
}
else if (item.t > 0) {
this.emit('expired', item.k, item.v);
this.remove(item.k);
}
this._itemsArray.shift();
}
};
/**
* Clean up the hash if the amount of dead items is double the
* amount of items in the hash. But only if the amount of items
* is greater than 10.
* @private
*/
ExpirableHash.prototype._clean = function() {
if (this._itemsArray.length > 10 &&
this._itemsArray.length > (this._items * 2)) {
var newArray = [];
this._itemsArray.forEach(function(item) {
if (item.t > 0) {
newArray.push(item);
}
});
this._itemsArray = newArray;
}
};