Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
#10 use injectable Promise implementation in caches
Browse files Browse the repository at this point in the history
  • Loading branch information
kjarmicki committed Apr 1, 2018
1 parent 0d07619 commit 3492f40
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 59 deletions.
109 changes: 56 additions & 53 deletions lib/caching/lru-cache.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,66 @@
var clone = require('clone');

module.exports = function(maxEntries) {
return new LRUCache(maxEntries);
};
module.exports = function(maxEntries, Promise) {
Promise = Promise || global.Promise;

/**
* A simple in-memory good guy cache implementation that has a cap on the maximum number of cached entries.
* If that number is exceeded, least recently used entries are dropped.
* @param maxEntries the maximum number of entries
* @constructor
*/
function LRUCache(maxEntries) {
this.maxEntries = maxEntries || 500;
this._entryOrder = [];
this._entryMap = {};
}
LRUCache.prototype = {
retrieve: function(key) {
var entry = this._entryMap[key];
if (entry !== undefined) {
this._markAsRecent(key);
return Promise.resolve(clone(entry));
} else {
return Promise.resolve(undefined);
}
},

store: function(key, value) {
value = clone(value);
var entry = this._entryMap[key];
if (entry !== undefined) {
this._entryMap[key] = value;
this._markAsRecent(key);
} else {
this._entryMap[key] = value;
this._entryOrder.unshift(key);
if (this._entryOrder.length > this.maxEntries)
this._discardLeastRecentlyUsed();
}
/**
* A simple in-memory good guy cache implementation that has a cap on the maximum number of cached entries.
* If that number is exceeded, least recently used entries are dropped.
* @param maxEntries the maximum number of entries
* @constructor
*/
function LRUCache(maxEntries) {
this.maxEntries = maxEntries || 500;
this._entryOrder = [];
this._entryMap = {};
}
LRUCache.prototype = {
retrieve: function (key) {
var entry = this._entryMap[key];
if (entry !== undefined) {
this._markAsRecent(key);
return Promise.resolve(clone(entry));
} else {
return Promise.resolve(undefined);
}
},

return Promise.resolve();
},
store: function (key, value) {
value = clone(value);
var entry = this._entryMap[key];
if (entry !== undefined) {
this._entryMap[key] = value;
this._markAsRecent(key);
} else {
this._entryMap[key] = value;
this._entryOrder.unshift(key);
if (this._entryOrder.length > this.maxEntries)
this._discardLeastRecentlyUsed();
}

evict: function(key) {
delete this._entryMap[key];
return Promise.resolve();
},
return Promise.resolve();
},

_markAsRecent: function(key) {
var index = this._entryOrder.indexOf(key);
if (index >= 0) {
this._entryOrder.splice(index, 1);
this._entryOrder.unshift(key);
evict: function (key) {
delete this._entryMap[key];
return Promise.resolve();
},

_markAsRecent: function (key) {
var index = this._entryOrder.indexOf(key);
if (index >= 0) {
this._entryOrder.splice(index, 1);
this._entryOrder.unshift(key);
}
},

_discardLeastRecentlyUsed: function () {
var key = this._entryOrder.pop();
delete this._entryMap[key];
}
},
};

_discardLeastRecentlyUsed: function() {
var key = this._entryOrder.pop();
delete this._entryMap[key];
}
return new LRUCache(maxEntries);
};


3 changes: 2 additions & 1 deletion lib/caching/null-cache.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = nullCache;

function nullCache() {
function nullCache(Promise) {
Promise = Promise || global.Promise;
return {
store: function(key, object) { return Promise.resolve(); },
retrieve: function(key) { return Promise.resolve(undefined); },
Expand Down
12 changes: 7 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,17 @@ function goodGuyHttp(config) {
var reqConfig = _.omit(config, OUR_CONFIGURATION_PROPERTIES);
config = _.pick(config, OUR_CONFIGURATION_PROPERTIES);

// determine promises implementation
if (config.usePromise === undefined)
config.usePromise = global.Promise;
var Promise = config.usePromise;

// sanitize configuration
if (config.cache === undefined)
config.cache = lruCache();
config.cache = lruCache(undefined, Promise);
if (config.cache === false)
config.cache = nullCache();
if (config.usePromise === undefined)
config.usePromise = global.Promise;
config.cache = nullCache(Promise);

var Promise = config.usePromise;
var promiseUtils = require('./promise-utils')(Promise);
var retryPromise = promiseUtils.retryPromise;
var collapsePromises = promiseUtils.collapsePromises;
Expand Down
23 changes: 23 additions & 0 deletions test/unit/lru-cache-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,27 @@ describe('LRUCache', function(){
assert.deepEqual(values, ['1', '2', '3', undefined, 'new']);
}).then(done).catch(done);
});

it('should be able to use custom Promise implementation', function(done) {
var spyPromise = createSpyPromise();
var lru = new LRUCache(2, spyPromise);
lru.store('hitchhiker', {answer: 42}).then(function() {
return lru.retrieve('hitchhiker');
}).then(function(object) {
assert.equal(spyPromise.resolveCallsCount(), 2);
}).then(done).catch(done);
});
});

function createSpyPromise() {
var resolveCallsCount = 0;
return {
resolve: function(value) {
resolveCallsCount += 1;
return Promise.resolve(value);
},
resolveCallsCount: function() {
return resolveCallsCount;
}
};
}

0 comments on commit 3492f40

Please sign in to comment.