Permalink
Browse files

Added contributors, MRU cache cleanup, closes #46

  • Loading branch information...
1 parent e2a50d1 commit 4ec97575033921ef7f7ee1e107eee392b3c4cc28 @1602 1602 committed Mar 16, 2012
Showing with 77 additions and 29 deletions.
  1. +1 −1 .travis.yml
  2. +48 −12 lib/abstract-class.js
  3. +1 −0 lib/schema.js
  4. +26 −15 package.json
  5. +1 −1 test/common_test.js
View
@@ -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
View
@@ -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;
@@ -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) {
@@ -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);
@@ -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;
});
@@ -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));
@@ -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);
});
@@ -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();
}
@@ -633,6 +634,7 @@ function defineScope(cls, targetClass, name, params, methods) {
// helper methods
//
+
function isdef(s) {
var undef;
return s !== undef;
@@ -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];
+}
+
View
@@ -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;
View
@@ -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"
}
}
View
@@ -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: {}
};

0 comments on commit 4ec9757

Please sign in to comment.