Backend half
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Output shape for endpoint discovery operations
|
||||
*/
|
||||
export type DiscoveredEndpoints = Array<{Address?: string, CachePeriodInMinutes?: number}>
|
||||
declare type EndpointRecords = Array<{
|
||||
Address: string;
|
||||
Expire: number;
|
||||
}>;
|
||||
export interface EndpointIdentifier {
|
||||
[key: string]: string | undefined;
|
||||
serviceId?: string;
|
||||
region?: string;
|
||||
accessKeyId?: string;
|
||||
operation?: string;
|
||||
}
|
||||
export declare class EndpointCache {
|
||||
readonly maxSize: number;
|
||||
private cache;
|
||||
constructor(maxSize?: number);
|
||||
readonly size: number;
|
||||
put(key: EndpointIdentifier | string, value: DiscoveredEndpoints): void;
|
||||
get(key: EndpointIdentifier | string): EndpointRecords | undefined;
|
||||
static getKeyString(key: EndpointIdentifier): string;
|
||||
private populateValue;
|
||||
empty(): void;
|
||||
remove(key: EndpointIdentifier | string): void;
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var LRU_1 = require("./utils/LRU");
|
||||
var CACHE_SIZE = 1000;
|
||||
/**
|
||||
* Inspired node-lru-cache[https://github.com/isaacs/node-lru-cache]
|
||||
*/
|
||||
var EndpointCache = /** @class */ (function () {
|
||||
function EndpointCache(maxSize) {
|
||||
if (maxSize === void 0) { maxSize = CACHE_SIZE; }
|
||||
this.maxSize = maxSize;
|
||||
this.cache = new LRU_1.LRUCache(maxSize);
|
||||
}
|
||||
;
|
||||
Object.defineProperty(EndpointCache.prototype, "size", {
|
||||
get: function () {
|
||||
return this.cache.length;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
EndpointCache.prototype.put = function (key, value) {
|
||||
var keyString = typeof key !== 'string' ? EndpointCache.getKeyString(key) : key;
|
||||
var endpointRecord = this.populateValue(value);
|
||||
this.cache.put(keyString, endpointRecord);
|
||||
};
|
||||
EndpointCache.prototype.get = function (key) {
|
||||
var keyString = typeof key !== 'string' ? EndpointCache.getKeyString(key) : key;
|
||||
var now = Date.now();
|
||||
var records = this.cache.get(keyString);
|
||||
if (records) {
|
||||
for (var i = records.length-1; i >= 0; i--) {
|
||||
var record = records[i];
|
||||
if (record.Expire < now) {
|
||||
records.splice(i, 1);
|
||||
}
|
||||
}
|
||||
if (records.length === 0) {
|
||||
this.cache.remove(keyString);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return records;
|
||||
};
|
||||
EndpointCache.getKeyString = function (key) {
|
||||
var identifiers = [];
|
||||
var identifierNames = Object.keys(key).sort();
|
||||
for (var i = 0; i < identifierNames.length; i++) {
|
||||
var identifierName = identifierNames[i];
|
||||
if (key[identifierName] === undefined)
|
||||
continue;
|
||||
identifiers.push(key[identifierName]);
|
||||
}
|
||||
return identifiers.join(' ');
|
||||
};
|
||||
EndpointCache.prototype.populateValue = function (endpoints) {
|
||||
var now = Date.now();
|
||||
return endpoints.map(function (endpoint) { return ({
|
||||
Address: endpoint.Address || '',
|
||||
Expire: now + (endpoint.CachePeriodInMinutes || 1) * 60 * 1000
|
||||
}); });
|
||||
};
|
||||
EndpointCache.prototype.empty = function () {
|
||||
this.cache.empty();
|
||||
};
|
||||
EndpointCache.prototype.remove = function (key) {
|
||||
var keyString = typeof key !== 'string' ? EndpointCache.getKeyString(key) : key;
|
||||
this.cache.remove(keyString);
|
||||
};
|
||||
return EndpointCache;
|
||||
}());
|
||||
exports.EndpointCache = EndpointCache;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
export declare class LRUCache<T> {
|
||||
private headerNode;
|
||||
private tailNode;
|
||||
private nodeMap;
|
||||
private size;
|
||||
private readonly sizeLimit;
|
||||
constructor(size: number);
|
||||
readonly length: number;
|
||||
private prependToList;
|
||||
private removeFromTail;
|
||||
private detachFromList;
|
||||
get(key: string): T | undefined;
|
||||
remove(key: string): void;
|
||||
put(key: string, value: T): void;
|
||||
empty(): void;
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var LinkedListNode = /** @class */ (function () {
|
||||
function LinkedListNode(key, value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
return LinkedListNode;
|
||||
}());
|
||||
var LRUCache = /** @class */ (function () {
|
||||
function LRUCache(size) {
|
||||
this.nodeMap = {};
|
||||
this.size = 0;
|
||||
if (typeof size !== 'number' || size < 1) {
|
||||
throw new Error('Cache size can only be positive number');
|
||||
}
|
||||
this.sizeLimit = size;
|
||||
}
|
||||
Object.defineProperty(LRUCache.prototype, "length", {
|
||||
get: function () {
|
||||
return this.size;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
LRUCache.prototype.prependToList = function (node) {
|
||||
if (!this.headerNode) {
|
||||
this.tailNode = node;
|
||||
}
|
||||
else {
|
||||
this.headerNode.prev = node;
|
||||
node.next = this.headerNode;
|
||||
}
|
||||
this.headerNode = node;
|
||||
this.size++;
|
||||
};
|
||||
LRUCache.prototype.removeFromTail = function () {
|
||||
if (!this.tailNode) {
|
||||
return undefined;
|
||||
}
|
||||
var node = this.tailNode;
|
||||
var prevNode = node.prev;
|
||||
if (prevNode) {
|
||||
prevNode.next = undefined;
|
||||
}
|
||||
node.prev = undefined;
|
||||
this.tailNode = prevNode;
|
||||
this.size--;
|
||||
return node;
|
||||
};
|
||||
LRUCache.prototype.detachFromList = function (node) {
|
||||
if (this.headerNode === node) {
|
||||
this.headerNode = node.next;
|
||||
}
|
||||
if (this.tailNode === node) {
|
||||
this.tailNode = node.prev;
|
||||
}
|
||||
if (node.prev) {
|
||||
node.prev.next = node.next;
|
||||
}
|
||||
if (node.next) {
|
||||
node.next.prev = node.prev;
|
||||
}
|
||||
node.next = undefined;
|
||||
node.prev = undefined;
|
||||
this.size--;
|
||||
};
|
||||
LRUCache.prototype.get = function (key) {
|
||||
if (this.nodeMap[key]) {
|
||||
var node = this.nodeMap[key];
|
||||
this.detachFromList(node);
|
||||
this.prependToList(node);
|
||||
return node.value;
|
||||
}
|
||||
};
|
||||
LRUCache.prototype.remove = function (key) {
|
||||
if (this.nodeMap[key]) {
|
||||
var node = this.nodeMap[key];
|
||||
this.detachFromList(node);
|
||||
delete this.nodeMap[key];
|
||||
}
|
||||
};
|
||||
LRUCache.prototype.put = function (key, value) {
|
||||
if (this.nodeMap[key]) {
|
||||
this.remove(key);
|
||||
}
|
||||
else if (this.size === this.sizeLimit) {
|
||||
var tailNode = this.removeFromTail();
|
||||
var key_1 = tailNode.key;
|
||||
delete this.nodeMap[key_1];
|
||||
}
|
||||
var newNode = new LinkedListNode(key, value);
|
||||
this.nodeMap[key] = newNode;
|
||||
this.prependToList(newNode);
|
||||
};
|
||||
LRUCache.prototype.empty = function () {
|
||||
var keys = Object.keys(this.nodeMap);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var node = this.nodeMap[key];
|
||||
this.detachFromList(node);
|
||||
delete this.nodeMap[key];
|
||||
}
|
||||
};
|
||||
return LRUCache;
|
||||
}());
|
||||
exports.LRUCache = LRUCache;
|
||||
Reference in New Issue
Block a user