Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

memoize-cache

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

memoize-cache - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

heap.js

3

package.json
{
"name": "memoize-cache",
"version": "0.1.0",
"version": "0.1.1",
"description": "A cache support for memoized functions",

@@ -31,4 +31,5 @@ "main": "index.js",

"dependencies": {
"md5-o-matic": "^0.1.1",
"sizeof": "^1.0.0"
}
}
var sizeof = require('sizeof');
var Heap = require('./heap');
var md5omatic = require('md5-o-matic');
/*

@@ -9,7 +10,20 @@

function sortByLessPopular(a, b) {
return a.times < b.times;
}
function sortByOldest(a, b) {
return a.ts < b.ts;
}
function removeByKey(key) {
return function (item) {
return item.key === key;
};
}
function Cache(opts) {
opts = opts || {};
this._cache = {}; // key, value
this._cacheKeys = []; // sorted by time {ts: xxx, key: xxx} new ones first
this.reset();

@@ -21,14 +35,29 @@ this._getCacheKey = opts.key || function () { return '_default'; };

Cache.prototype.push = function cache_push(args, output) {
Cache.prototype.getCacheKey = function cache_getCacheKey(args) {
var k = this._getCacheKey.apply(undefined, args);
if (typeof k !== 'string') {
k = JSON.stringify(k);
k = md5omatic(JSON.stringify(k));
}
return k;
};
Cache.prototype.push = function cache_push(args, output) {
var lru;
var k = this.getCacheKey(args);
if (k in this._cache) return;
if(this._LRU.size() === this._maxLen) {
lru = this._LRU.pop();
delete this._cache[lru.key];
this._oldest.remove(removeByKey(lru.key));
}
this._cache[k] = output;
this._cacheKeys.unshift({
this._LRU.push({key: k, times: 0});
this._oldest.push({
key: k,
ts: Date.now()
});
this._purgeByLen();
};

@@ -38,32 +67,22 @@

// remove old entries
var maxAge = this._maxAge;
var cache = this._cache;
var oldest;
var now = Date.now();
var now = Date.now();
this._cacheKeys = this._cacheKeys.filter(function (item) {
if (item.ts + maxAge < now ) {
delete cache[item.key];
return false;
while (this._oldest.size()) {
oldest = this._oldest.pop();
if (oldest.ts + this._maxAge < now) {
delete this._cache[oldest.key];
this._LRU.remove(removeByKey(oldest.key));
}
return true;
});
else {
this._oldest.push(oldest);
break;
}
}
};
Cache.prototype._purgeByLen = function cache__purgeByLen() {
// remove old entries
var maxLen = this._maxLen;
var cache = this._cache;
// trim cache
var keysToRemove = this._cacheKeys.slice(maxLen, Infinity);
keysToRemove.forEach(function (item) {
var k = item.key;
delete cache[k];
});
this._cacheKeys = this._cacheKeys.slice(0, maxLen);
};
Cache.prototype.reset = function cache_reset() {
this._cache = {}; // key, value
this._cacheKeys = []; // sorted by time {ts: xxx, key: xxx}
this._LRU = new Heap(sortByLessPopular);
this._oldest = new Heap(sortByOldest);
};

@@ -74,13 +93,15 @@

cached = false,
lru,
key;
try {
this._purgeByAge(); // purge stale cache entries
key = this._getCacheKey.apply(undefined, args);
if (typeof key !== 'string') {
key = JSON.stringify(key);
}
key = this.getCacheKey(args);
if (key in this._cache) {
cached = true;
hit = this._cache[key]; // cache hit!
lru = this._LRU.remove(removeByKey(key));
lru.times++;
this._LRU.push(lru);
}

@@ -104,5 +125,5 @@ }

Cache.prototype.len = function cache_len() {
return this._cacheKeys.length;
return this._LRU.size();
};
module.exports = Cache;
memoize-cache
=============
A configurable cache support for memoized functions.
A configurable cache support for memoized functions. It is lightweight so it can run in the browser without any problem.

@@ -12,8 +12,10 @@ A note about the API

The constructor takes an option object with 3 optional attributes:
* key: a function used to extract the cache key (used in the push and query method for storing, retrieving the cached value). The key returned should be a string or it will be converted to JSON. Default: a function returning a fixed key.
* key: a function used to extract the cache key (used in the push and query method for storing, retrieving the cached value). The key returned should be a string or it will be converted to JSON and then md5. Default: a function returning a fixed key.
* maxAge: the maximum age of the item stored in the cache (in ms). Default: Infinity
* maxLen: the maximum number of items stored in the cache. Default: Infinity
* maxLen: the maximum number of items stored in the cache. Default: Infinity. Cache items will be purged using an LRU algorithm
Example:
```js
var Cache = require('memoize-cache/ram-cache'); // or require('memoize-cache').ramCache;
// no values, uses always the same key for store any value

@@ -20,0 +22,0 @@ var cache = new Cache();

@@ -6,2 +6,9 @@ var assert = require('chai').assert;

it('must translate args to key', function () {
var cache = new Cache({key: function (n) {return n;}});
assert.equal(cache.getCacheKey(['1']), '1');
assert.equal(cache.getCacheKey([1]), 'c4ca4238a0b923820dcc509a6f75849b');
assert.equal(cache.getCacheKey([{d:1}]), 'dc6f789c90af7a7f8156af120f33e3be');
});
it('must configure cache: default key', function (done) {

@@ -72,3 +79,3 @@ var cache = new Cache();

assert.equal(res1.cached, true);
assert.equal(res1.key, '[1,2]');
assert.equal(res1.key, 'f79408e5ca998cd53faf44af31e6eb45');
assert.equal(res1.hit, 'result1');

@@ -87,3 +94,3 @@ done();

assert.equal(res1.cached, true);
assert.equal(res1.key, '1');
assert.equal(res1.key, 'c4ca4238a0b923820dcc509a6f75849b');
assert.equal(res1.hit, 'result1');

@@ -102,3 +109,3 @@ done();

assert.equal(res1.cached, true);
assert.equal(res1.key, '[1,2]');
assert.equal(res1.key, 'f79408e5ca998cd53faf44af31e6eb45');
assert.equal(res1.hit, 'result1');

@@ -117,3 +124,3 @@ done();

assert.equal(res1.cached, true);
assert.equal(res1.key, '8');
assert.equal(res1.key, 'c9f0f895fb98ab9159f51fd0297e236d');
assert.equal(res1.hit, 'result1');

@@ -131,14 +138,10 @@ done();

}, maxLen: 2});
cache.push([{test: 1}], 'result1');
cache.push([{test: 2}], 'result2');
cache.push([{test: 3}], 'result3');
cache.push([{test: '1'}], 'result1');
cache.push([{test: '2'}], 'result2');
});
it('must be right size', function () {
assert.equal(cache.len(), 2);
});
it('must not be cached (purged)', function (done) {
cache.query([{test: 1}], function (err, res1) {
assert.equal(res1.cached, false);
it('must be on the top of the heap', function (done) {
assert.deepEqual(cache._LRU.peek(), {key: '1', times: 0});
cache.query([{test: '1'}], function () {
assert.deepEqual(cache._LRU.peek(), {key: '2', times: 0});
done();

@@ -148,18 +151,38 @@ });

it('must not be cached 1', function (done) {
cache.query([{test: 2}], function (err, res2) {
assert.equal(res2.cached, true);
assert.equal(res2.key, '2');
assert.equal(res2.hit, 'result2');
done();
describe('remove one', function () {
beforeEach(function (done) {
cache.query([{test: '2'}], function () {
cache.push([{test: '3'}], 'result3');
done();
});
});
});
it('must be right size', function () {
assert.equal(cache.len(), 2);
});
it('must not be cached 2', function (done) {
cache.query([{test: 3}], function (err, res3) {
assert.equal(res3.cached, true);
assert.equal(res3.key, '3');
assert.equal(res3.hit, 'result3');
done();
it('must not be cached (purged)', function (done) {
cache.query([{test: '1'}], function (err, res1) {
assert.equal(res1.cached, false);
done();
});
});
it('must not be cached 1', function (done) {
cache.query([{test: '2'}], function (err, res2) {
assert.equal(res2.cached, true);
assert.equal(res2.key, '2');
assert.equal(res2.hit, 'result2');
done();
});
});
it('must not be cached 2', function (done) {
cache.query([{test: '3'}], function (err, res3) {
assert.equal(res3.cached, true);
assert.equal(res3.key, '3');
assert.equal(res3.hit, 'result3');
done();
});
});
});

@@ -175,7 +198,7 @@ });

}, maxAge: 30});
cache.push([{test: 1}], 'result1');
cache.push([{test: '1'}], 'result1');
});
it('must be cached', function (done) {
cache.query([{test: 1}], function (err, res1) {
cache.query([{test: '1'}], function (err, res1) {
assert.equal(res1.cached, true);

@@ -190,3 +213,3 @@ assert.equal(res1.key, '1');

setTimeout(function () {
cache.query([{test: 1}], function (err, res1) {
cache.query([{test: '1'}], function (err, res1) {
assert.equal(res1.cached, true);

@@ -202,7 +225,13 @@ assert.equal(res1.key, '1');

setTimeout(function () {
cache.query([{test: 1}], function (err, res1) {
cache.push([{test: '2'}], 'result2');
cache.query([{test: '1'}], function (err, res1) {
assert.equal(res1.cached, false);
assert.equal(res1.key, '1');
assert.isUndefined(res1.hit);
done();
cache.query([{test: '2'}], function (err, res1) {
assert.equal(res1.cached, true);
assert.equal(res1.key, '2');
assert.equal(res1.hit, 'result2');
done();
});
});

@@ -217,3 +246,3 @@ }, 40);

}});
cache.push([{test: 1}], 'result1');
cache.push([{test: '1'}], 'result1');

@@ -220,0 +249,0 @@ cache.reset();

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc