Permalink
Browse files

Repo clean up, with extra quality checks and passing tests

  • Loading branch information...
serby committed Jan 8, 2014
1 parent 41e6d3a commit a99e873296cecf06bca8f49ca4c79c587fca5cc7
Showing with 122 additions and 135 deletions.
  1. +2 −17 .gitignore
  2. +2 −0 .jshintignore
  3. 0 .nodemonignore
  4. +0 −15 Makefile
  5. +15 −15 benchmark/bench.js
  6. +50 −58 lib/cache.js
  7. +36 −27 package.json
  8. +17 −3 test/cache.test.js
View
@@ -1,17 +1,2 @@
# Windows
Thumbs.db
# Vim
.*.sw[a-z]
*.un~i
tags
# OsX
.DS_Store
Icon?
._*
.Spotlight-V100
.Trashes
# nodejs npm modules
/node_modules
node_modules
coverage
View
@@ -0,0 +1,2 @@
node_modules
coverage
View
No changes.
View

This file was deleted.

Oops, something went wrong.
View
@@ -1,8 +1,8 @@
function time(fn) {
var start = Date.now();
fn();
return Date.now() - start;
var start = Date.now()
fn()
return Date.now() - start
}
@@ -26,27 +26,27 @@ var tests = {}
, count: large
, maxLength: Math.round(large * 0.75)
}
];
]
for (var type in types) {
var values = types[type];
types.forEach(function(values) {
tests['ttl-lru-cache ' + values.name] = require('./engine.bench')(values.count, function() {
return require('../lib/cache')({ maxLength: values.maxLength, gcInterval: 10000 });
});
return require('../lib/cache')({ maxLength: values.maxLength, gcInterval: 10000 })
})
tests['lru-cache ' + values.name] = require('./engine.bench')(values.count, function() {
var LRU = require('lru-cache')
, cache = LRU(values.maxLength);
return cache;
});
}
, cache = LRU(values.maxLength)
return cache
})
})
for (var key in tests) {
console.log(key);
console.log(key)
for (var subKey in tests[key]) {
if (subKey === 'end') {
tests[key][subKey]();
tests[key][subKey]()
} else {
console.log(subKey, time(tests[key][subKey]));
console.log(subKey, time(tests[key][subKey]))
}
}
}
View
@@ -1,120 +1,112 @@
var _ = require('lodash')
, EventEmitter = require('events').EventEmitter;
var extend = require('lodash.assign')
, EventEmitter = require('events').EventEmitter
module.exports = function(options) {
module.exports = function(opts) {
var cache
, lru
, lruId = 0
, gcHandle
, instance
;
options = _.extend({
gcInterval: 30000, // How often GC happens
maxLength: 1000 // Maximum number of items that can be held in the LRU cache by default.
}, options);
, instance = new EventEmitter()
, options = extend(
{ gcInterval: 30000 // How often GC happens
, maxLength: 1000 // Maximum number of items that can be held in the cache by default.
, lruWriteCleanUp: 100 // Run the LRU clean up every 'lruWriteCleanUp' writes
}, opts)
function clear() {
cache = {};
lru = [];
}
function hasOwn (object, key) {
return object.hasOwnProperty(key);
cache = {}
lru = {}
}
function del(key) {
var item = cache[key];
var item = cache[key]
if (item) {
delete lru[item.lru];
delete cache[key];
delete cache[key]
}
}
function garbageCollection() {
Object.keys(cache).forEach(function(key) {
var item = cache[key];
var item = cache[key]
if (item.expire <= Date.now()) {
expire(key, item);
expire(key, item)
}
});
lruClean();
})
lruClean()
}
function lruClean() {
var overage = Object.keys(cache).length - options.maxLength
, cacheId
, lruKeys = Object.keys(lru)
;
, lruKey
for (var i = 0; i < overage; i++) {
cacheId = lru.shift();
var item = cache[cacheId];
delete cache[cacheId];
lruKey = lruKeys.shift()
cacheId = lru[lruKey];
delete lru[lruKey];
delete cache[cacheId]
}
}
function expire(key, item) {
del(key);
instance.emit("expired", key, item.value);
del(key)
instance.emit('expired', key, item.value)
}
clear();
gcHandle = setInterval(garbageCollection, options.gcInterval);
clear()
gcHandle = setInterval(garbageCollection, options.gcInterval)
instance = {
extend(instance, {
set: function(key, value, ttl) {
if (typeof key === 'undefined') {
throw new Error('Invalid key undefined');
throw new Error('Invalid key undefined')
}
var item = { value: value, lru: lruId };
var item = { value: value, lru: lruId }
if (ttl) {
item.expire = Date.now() + ttl;
item.expire = Date.now() + ttl
}
cache[key] = item;
lru[lruId] = key;
lruId++;
if (lruId % 100 === 0) {
lruClean();
cache[key] = item
lru[lruId] = key
lruId++
if (lruId % options.lruWriteCleanUp === 0) {
lruClean()
}
},
get: function(key) {
var response
, item = cache[key];
, item = cache[key]
if (item) {
if ((item.expire) && (item.expire < Date.now())) {
expire(key, item);
return undefined;
expire(key, item)
return undefined
}
response = item.value;
delete lru[item.lruId];
lru[lruId] = key;
item.lruId = lruId;
lruId++;
lru[lruId] = key
item.lru = lruId
lruId++
}
return response;
return response
},
del: del,
clear: clear,
gc: lruClean,
size: function() {
garbageCollection();
return Object.keys(cache).length;
garbageCollection()
return Object.keys(cache).length
},
dump: function() {
return cache;
return cache
},
close: function() {
clearInterval(gcHandle);
clearInterval(gcHandle)
}
};
instance = _.extend(instance, new EventEmitter());
})
return instance;
};
return instance
}
View
@@ -1,28 +1,37 @@
{ "author": "Paul Serby <paul@serby.net>"
, "name": "ttl-lru-cache"
, "description": "A fast in memory cache with TTL and LRU support"
, "version": "0.0.2"
, "tags":
[ "cache"
, "lru"
, "ttl"]
, "repository":
{ "type": "git"
, "url": "git@github.com:serby/ttl-lru-cache"
{
"author": "Paul Serby <paul@serby.net>",
"name": "ttl-lru-cache",
"description": "A fast in memory cache with TTL and LRU support",
"version": "0.0.2",
"tags": [
"cache",
"lru",
"ttl"
],
"repository": {
"type": "git",
"url": "git@github.com:serby/ttl-lru-cache"
},
"scripts": {
"lint": "./node_modules/.bin/jshint . --reporter=./node_modules/jshint-full-path/index.js",
"pretest": "npm run-script lint",
"test": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -R spec -r should",
"posttest": "./node_modules/.bin/istanbul check-coverage && rm -rf coverage",
"prepublish": "npm test && npm prune"
},
"main": "lib/cache.js",
"engines": {
"node": ">=0.6.0"
},
"dependencies": {
"lodash.assign": "~2.4.1"
},
"devDependencies": {
"mocha": "1",
"should": "2",
"lru-cache": "*",
"istanbul": "~0.2.1",
"jshint": "~2.4.0",
"jshint-full-path": "~1.1.1"
}
, "main": "lib/cache.js"
, "scripts":
{ "test": "mocha -r should"
}
, "engines":
{ "node": ">=0.6.0"
}
, "dependencies":
{ "lodash": "*"
}
, "devDependencies":
{ "mocha": "*"
, "should": "*"
, "lru-cache": "*"
}
}
}
View
@@ -69,20 +69,19 @@ describe('ttl-lru-cache', function() {
, a = { a: 1 }
, b = { ref: a }
a.ref = b
memory.set('a', a)
memory.get('a').ref.should.eql(b)
})
it('should not allow undefined key', function() {
var memory = createCache()
var memory = createCache();
(function() {
memory.set(undefined, '')
}).should.throwError('Invalid key undefined')
})
it('should remove least recently used from the cache first', function() {
it('should remove least recently used from the cache first base on write', function() {
var memory = createCache({ maxLength: 3 })
@@ -94,6 +93,21 @@ describe('ttl-lru-cache', function() {
memory.size().should.eql(3)
memory.set('d', 'd')
memory.size().should.eql(3)
true.should.eql(memory.get('a') === undefined)
})
it.skip('should remove least recently used from the cache first base on read', function() {
var memory = createCache({ maxLength: 3, lruWriteCleanUp: 1 })
memory.set('a', 'a')
memory.set('b', 'b')
memory.set('c', 'c')
memory.get('a')
memory.get('a').should.eql('a')
memory.set('d', 'd')
memory.gc()
true.should.eql(memory.get('b') === undefined)
})
it('should not increase the length when overwriting a value', function() {

0 comments on commit a99e873

Please sign in to comment.