Skip to content

Commit

Permalink
Added contributors, MRU cache cleanup, closes 1602#46
Browse files Browse the repository at this point in the history
  • Loading branch information
1602 committed Mar 16, 2012
1 parent e2a50d1 commit 4ec9757
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.4
- 0.4.12
- 0.6
before_install:
- git submodule init && git submodule --quiet update
Expand Down
60 changes: 48 additions & 12 deletions lib/abstract-class.js
Expand Up @@ -5,6 +5,7 @@ var Validatable = require('./validatable').Validatable;
var Hookable = require('./hookable').Hookable;
var util = require('util');
var jutil = require('./jutil');
var DEFAULT_CACHE_LIMIT = 1000;

exports.AbstractClass = AbstractClass;

Expand Down Expand Up @@ -154,7 +155,7 @@ AbstractClass.create = function (data, callback) {
this._adapter().create(modelName, data, function (err, id) {
if (id) {
defineReadonlyProp(obj, 'id', id);
this.constructor.cache[id] = obj;
addToCache(this.constructor, obj);
}
done.call(this, function () {
if (callback) {
Expand All @@ -178,14 +179,15 @@ AbstractClass.find = function find(id, cb) {
this.schema.adapter.find(this.modelName, id, function (err, data) {
var obj = null;
if (data) {
if (this.cache[data.id]) {
obj = this.cache[data.id];
var cached = getCached(this, data.id);
if (cached) {
obj = cached;
substractDirtyAttributes(obj, data);
this.call(obj, data);
} else {
data.id = id;
obj = new this(data);
this.cache[data.id] = obj;
addToCache(this, id);
}
}
cb(err, obj);
Expand All @@ -209,14 +211,15 @@ AbstractClass.all = function all(params, cb) {
collection = data.map(function (d) {
var obj = null;
// do not create different instances for the same object
if (d.id && constr.cache[d.id]) {
obj = constr.cache[d.id];
var cached = getCached(constr, d.id);
if (cached) {
obj = cached;
// keep dirty attributes untouthed (remove from dataset)
substractDirtyAttributes(obj, d);
constr.call(obj, d);
} else {
obj = new constr(d);
if (d.id) constr.cache[d.id] = obj;
if (obj.id) addToCache(constr, obj);
}
return obj;
});
Expand Down Expand Up @@ -248,9 +251,7 @@ function substractDirtyAttributes(object, data) {
AbstractClass.destroyAll = function destroyAll(cb) {
this.schema.adapter.destroyAll(this.modelName, function (err) {
if (!err) {
Object.keys(this.cache).forEach(function (id) {
delete this.cache[id];
}.bind(this));
clearCache(this);
}
cb(err);
}.bind(this));
Expand Down Expand Up @@ -365,7 +366,7 @@ AbstractClass.prototype.toObject = function (onlySchema) {
AbstractClass.prototype.destroy = function (cb) {
this.trigger('destroy', function (destroyed) {
this._adapter().destroy(this.constructor.modelName, this.id, function (err) {
delete this.constructor.cache[this.id];
removeFromCache(this.constructor, this.id);
destroyed(function () {
cb && cb(err);
});
Expand Down Expand Up @@ -442,7 +443,7 @@ AbstractClass.prototype.propertyChanged = function (attr) {
};

AbstractClass.prototype.reload = function (cb) {
var obj = this.constructor.cache[this.id];
var obj = getCached(this.constructor, this.id);
if (obj) {
obj.reset();
}
Expand Down Expand Up @@ -633,6 +634,7 @@ function defineScope(cls, targetClass, name, params, methods) {

// helper methods
//

function isdef(s) {
var undef;
return s !== undef;
Expand All @@ -657,3 +659,37 @@ function defineReadonlyProp(obj, key, value) {
});
}

function addToCache(constr, obj) {
touchCache(constr, obj.id);
constr.cache[obj.id] = obj;
}

function touchCache(constr, id) {
var cacheLimit = constr.CACHE_LIMIT || DEFAULT_CACHE_LIMIT;

var ind = constr.mru.indexOf(id);
if (~ind) constr.mru.splice(ind, 1);
if (constr.mru.length >= cacheLimit * 2) {
for (var i = 0; i < cacheLimit;i += 1) {
delete constr.cache[constr.mru[i]];
}
constr.mru.splice(0, cacheLimit);
}
}

function getCached(constr, id) {
if (id) touchCache(constr, id);
return id && constr.cache[id];
}

function clearCache(constr) {
constr.cache = {};
constr.mru = [];
}

function removeFromCache(constr, id) {
var ind = constr.mru.indexOf(id);
if (!~ind) constr.mru.splice(ind, 1);
delete constr.cache[id];
}

1 change: 1 addition & 0 deletions lib/schema.js
Expand Up @@ -154,6 +154,7 @@ Schema.prototype.define = function defineClass(className, properties, settings)
hiddenProperty(newClass, 'schema', schema);
hiddenProperty(newClass, 'modelName', className);
hiddenProperty(newClass, 'cache', {});
hiddenProperty(newClass, 'mru', []);

// setup inheritance
newClass.__proto__ = AbstractClass;
Expand Down
41 changes: 26 additions & 15 deletions package.json
@@ -1,32 +1,43 @@
{
"name": "jugglingdb",
"author": "Anatoliy Chakkaev",
"description": "ORM for every database: redis, mysql, neo4j, mongodb, postgres, sqlite",
"version": "0.1.3",
"version": "0.1.4",
"author": "Anatoliy Chakkaev <rpm1602@gmail.com>",
"contributors": [
{ "name": "Anatoliy Chakkaev", "email": "rpm1602@gmail.com" },
{ "name": "Julien Guimont", "email": "julien.guimont@gmail.com" },
{ "name": "Henri Bergius", "email": "henri.bergius@iki.fi" },
{ "name": "redvulps", "email": "fabopereira@gmail.com" },
{ "name": "Amir M. Mahmoudi", "email": "a@geeknux.com" },
{ "name": "Justinas Stankevičius", "email": "justinas@justinas.me" },
{ "name": "Felipe Sateler", "email": "fsateler@gmail.com" },
{ "name": "Rick O'Toole", "email": "patrick.n.otoole@gmail.com" }
],
"repository": {
"type": "git",
"url": "https://github.com/1602/jugglingdb"
},
"main": "index.js",
"scripts": {
"test": "nodeunit test/*_test*"
},
"engines": [
"node >= 0.4.0"
"node >= 0.4.12"
],
"dependencies": {
"node-uuid": "*"
"node-uuid": ">= 1.3.3"
},
"devDependencies": {
"redis": ">= 0.6.7",
"mongoose": ">= 2.2.3",
"mysql": ">= 0.9.4",
"sequelize": "*",
"pg": "*",
"sqlite3": "*",
"nodeunit": ">= 0",
"coffee-script": ">= 0",
"riak-js": ">= 0",
"neo4j": ">= 0",
"mongodb": "*"
"coffee-script": ">= 1.2.0",
"nodeunit": ">= 0.6.4",
"redis": ">= 0.6.7",
"mongoose": ">= 2.2.3",
"mysql": ">= 0.9.4",
"pg": ">= 0.6.9",
"sqlite3": ">= 2.1.1",
"riak-js": ">= 0.4.1",
"neo4j": ">= 0.2.5",
"mongodb": ">= 0.9.9",
"felix-couchdb": ">= 1.0.3"
}
}
2 changes: 1 addition & 1 deletion test/common_test.js
Expand Up @@ -18,7 +18,7 @@ var schemas = {
},
neo4j: { url: 'http://localhost:7474/' },
mongoose: { url: 'mongodb://travis:test@localhost:27017/myapp' },
mongodb: { url: 'mongodb://travis:test@localhost:27017/myapp' },
mongodb: { url: 'mongodb://travis:test@localhost:27017/myapp' },
redis: {},
memory: {}
};
Expand Down

0 comments on commit 4ec9757

Please sign in to comment.