kopia lustrzana https://github.com/c9/core
Merge pull request +12410 from c9/stats-via-extension
Stats via vfs extensionpull/263/head
commit
26e1a7be83
|
@ -0,0 +1,82 @@
|
|||
|
||||
var Cache = function(maxSize, age) {
|
||||
this._maxSize = (parseInt(maxSize, 10) === maxSize) ? maxSize : 1000;
|
||||
this._maxAge = (parseInt(age, 10) === age) ? age : 5000;
|
||||
this._items = {};
|
||||
this._keys = [];
|
||||
};
|
||||
|
||||
var proto = Cache.prototype;
|
||||
|
||||
proto.set = function(key, value) {
|
||||
var item = this._items[key];
|
||||
if (item) {
|
||||
this.delete(key);
|
||||
}
|
||||
|
||||
this._keys.push(key);
|
||||
this._items[key] = {
|
||||
value: value,
|
||||
lastAccessed: Date.now()
|
||||
};
|
||||
|
||||
this.purge();
|
||||
};
|
||||
|
||||
proto.has = function(key) {
|
||||
var item = this._items[key];
|
||||
return (item && !this._hasExpired(item));
|
||||
};
|
||||
|
||||
proto.get = function(key) {
|
||||
var item = this._items[key];
|
||||
if (item && !this._hasExpired(item)) {
|
||||
return item.value;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
proto.delete = function(key) {
|
||||
delete this._items[key];
|
||||
this._keys.splice(this._keys.indexOf(key), 1);
|
||||
};
|
||||
|
||||
proto.purge = function() {
|
||||
if (this._keys.length > this._maxSize) {
|
||||
this._purgeItems();
|
||||
}
|
||||
};
|
||||
|
||||
proto.size = function() {
|
||||
return this._keys.length;
|
||||
};
|
||||
|
||||
proto._purgeItems = function() {
|
||||
var maxSize = this._maxSize * 0.75;
|
||||
|
||||
// Remove epired items
|
||||
this._keys.forEach(function(key) {
|
||||
var item = this._items[key];
|
||||
if (this._hasExpired(item)) {
|
||||
this.delete(key);
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Remove least used items
|
||||
if (this._keys.length > maxSize) {
|
||||
this._keys = this._keys.sort(function(a, b) {
|
||||
return this._items[b].lastAccessed - this._items[a].lastAccessed;
|
||||
}.bind(this));
|
||||
|
||||
while (this._keys.length > maxSize) {
|
||||
var key = this._keys.pop();
|
||||
this.delete(key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
proto._hasExpired = function(item) {
|
||||
return (Date.now() - item.lastAccessed) > this._maxAge;
|
||||
};
|
||||
|
||||
module.exports = Cache;
|
|
@ -0,0 +1,188 @@
|
|||
"use strict";
|
||||
"use server";
|
||||
|
||||
|
||||
var assert = require("assert");
|
||||
var Cache = require("./cache");
|
||||
|
||||
require("c9/inline-mocha")(module);
|
||||
|
||||
describe("Cache", function() {
|
||||
var cache;
|
||||
var maxSize = 5;
|
||||
var age = 10;
|
||||
|
||||
beforeEach(function() {
|
||||
cache = new Cache(maxSize, age) ;
|
||||
});
|
||||
|
||||
describe("set", function() {
|
||||
it("should add the item to the cache", function(){
|
||||
var item = { a: 1 };
|
||||
var key = "foo/bar";
|
||||
|
||||
cache.set(key, item);
|
||||
var cachedItem = cache.get(key);
|
||||
assert.equal(cachedItem, item);
|
||||
});
|
||||
it("should increment size", function() {
|
||||
var item = { a: 1 };
|
||||
|
||||
cache.set("foo/bar", item);
|
||||
cache.set("foo/baz", item);
|
||||
cache.set("foo/bir", item);
|
||||
cache.set("foo/biz", item);
|
||||
cache.set("foo/bur", item);
|
||||
|
||||
assert(cache.size(), 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("get", function() {
|
||||
it("should return item when called within age", function() {
|
||||
var item = { a: 1 };
|
||||
var key = "foo/bar";
|
||||
|
||||
cache.set(key, item);
|
||||
var cachedItem = cache.get(key);
|
||||
assert.equal(cachedItem, item);
|
||||
});
|
||||
it("should return `null` if item expired", function(done) {
|
||||
var item = { a: 1 };
|
||||
var key = "foo/bar";
|
||||
|
||||
var cache = new Cache(maxSize, 0) ;
|
||||
cache.set(key, item);
|
||||
|
||||
// Do we use sinon to make this sync?
|
||||
setTimeout(function() {
|
||||
var cachedItem = cache.get(key);
|
||||
assert.equal(cachedItem, null);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("delete", function() {
|
||||
it("should remove item from cache", function() {
|
||||
var item = { a: 1 };
|
||||
var key = "foo/bar";
|
||||
|
||||
cache.set(key, item);
|
||||
cache.delete(key);
|
||||
var cachedItem = cache.get(key);
|
||||
assert.equal(cachedItem, null);
|
||||
});
|
||||
|
||||
it("should decrement size", function() {
|
||||
var item = { a: 1 };
|
||||
var key = "foo/bar";
|
||||
|
||||
cache.set(key, item);
|
||||
cache.delete(key);
|
||||
assert.equal(cache.size(), 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("purge", function() {
|
||||
it("should not purge when maxSize is not reached", function() {
|
||||
var item = { a: 1 };
|
||||
|
||||
var cache = new Cache(7) ;
|
||||
|
||||
cache.set("foo/bar", item);
|
||||
cache.set("foo/baz", item);
|
||||
cache.set("foo/bir", item);
|
||||
cache.set("foo/biz", item);
|
||||
|
||||
assert.equal(cache.size(), 4);
|
||||
});
|
||||
|
||||
it("should purge when maxSize is reached", function() {
|
||||
var item = { a: 1 };
|
||||
|
||||
var cache = new Cache(10) ;
|
||||
|
||||
cache.set("1", item);
|
||||
cache.set("2", item);
|
||||
cache.set("3", item);
|
||||
cache.set("4", item);
|
||||
cache.set("5", item);
|
||||
cache.set("6", item);
|
||||
cache.set("7", item);
|
||||
cache.set("8", item);
|
||||
cache.set("9", item);
|
||||
cache.set("10", item);
|
||||
cache.set("11", item);
|
||||
|
||||
assert.equal(cache.size(), 7);
|
||||
});
|
||||
|
||||
it("should purge the least recently used items", function(done) {
|
||||
var item = { a: 1 };
|
||||
|
||||
var cache = new Cache(10, 0) ;
|
||||
|
||||
cache.set("1", item);
|
||||
cache.set("2", item);
|
||||
cache.set("3", item);
|
||||
cache.set("4", item);
|
||||
cache.set("5", item);
|
||||
cache.set("6", item);
|
||||
cache.set("7", item);
|
||||
cache.set("8", item);
|
||||
cache.set("9", item);
|
||||
cache.set("10", item);
|
||||
|
||||
// New cache hits
|
||||
setTimeout(function() {
|
||||
cache.get("1");
|
||||
cache.get("2");
|
||||
cache.get("10");
|
||||
cache.get("4");
|
||||
cache.get("5");
|
||||
cache.get("6");
|
||||
|
||||
// Trigger purge
|
||||
cache.set("11", item);
|
||||
|
||||
var cachedItem = cache.get("7");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("8");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("9");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("3");
|
||||
assert.equal(cachedItem, null);
|
||||
|
||||
done();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
it("should purge expired items", function(done) {
|
||||
var item = { a: 1 };
|
||||
|
||||
var cache = new Cache(5, 0) ;
|
||||
|
||||
cache.set("1", item);
|
||||
cache.set("2", item);
|
||||
cache.set("3", item);
|
||||
cache.set("4", item);
|
||||
|
||||
setTimeout(function() {
|
||||
cache.set("5", item);
|
||||
|
||||
var cachedItem = cache.get("1");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("2");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("3");
|
||||
assert.equal(cachedItem, null);
|
||||
cachedItem = cache.get("4");
|
||||
assert.equal(cachedItem, null);
|
||||
|
||||
done();
|
||||
}, 2);
|
||||
});
|
||||
});
|
||||
});
|
Ładowanie…
Reference in New Issue