Comparing version 0.0.15 to 0.0.16
@@ -11,12 +11,15 @@ 'use strict'; | ||
Cache.prototype.has = function(id) { | ||
return this.store.hasOwnProperty(id); | ||
Cache.prototype.has = function (id) { | ||
if (id) { | ||
return this.store.hasOwnProperty(id); | ||
} | ||
return false; | ||
}; | ||
Cache.prototype.prune = function() { | ||
Cache.prototype.prune = function () { | ||
if (this.keys > this.size) { | ||
var self = this; | ||
process.nextTick(function () { | ||
var objKeys = Object.keys(self.store), | ||
pruned = self.keys - self.size; | ||
var objKeys = Object.keys(self.store); | ||
var pruned = self.keys - self.size; | ||
@@ -29,3 +32,3 @@ objKeys.sort(function (a, b) { | ||
for (i = 0; i < pruned; i++) { | ||
delete(self.store[objKeys[i]]); | ||
delete (self.store[objKeys[i]]); | ||
} | ||
@@ -37,3 +40,3 @@ self.keys -= pruned; | ||
Cache.prototype.get = function(id) { | ||
Cache.prototype.get = function (id) { | ||
if (this.store.hasOwnProperty(id)) { | ||
@@ -43,3 +46,3 @@ var entry = this.store[id]; | ||
if(entry.atime + this.ttl < now) { | ||
if (entry.atime + this.ttl < now) { | ||
this.del(id); | ||
@@ -55,3 +58,3 @@ // do not return null since it can mean a not found | ||
Cache.prototype.set = function(id, doc) { | ||
Cache.prototype.set = function (id, doc) { | ||
if (!this.has(id)) { | ||
@@ -70,11 +73,20 @@ this.keys++; | ||
Cache.prototype.del = function(id) { | ||
if (id) { | ||
delete(this.store[id]); | ||
Cache.prototype.del = function (id) { | ||
if (this.has(id)) { | ||
delete (this.store[id]); | ||
this.keys--; | ||
} else { | ||
this.store = {}; | ||
} | ||
}; | ||
Cache.prototype.reset = function () { | ||
var keys = Object.keys(this.store); | ||
var i; | ||
for (i = 0; i < keys.length; i++) { | ||
if (this.store.hasOwnProperty(keys[i])) { | ||
delete this.store[keys[i]]; | ||
} | ||
} | ||
this.keys = 0; | ||
}; | ||
module.exports = Cache; |
@@ -33,2 +33,6 @@ 'use strict'; | ||
db: null, | ||
/** | ||
* @memberOf ODM | ||
*/ | ||
queryCache: null, | ||
@@ -43,3 +47,3 @@ /** | ||
*/ | ||
connect: function(url, options, callback) { | ||
connect: function (url, options, callback) { | ||
var self = this; | ||
@@ -54,8 +58,14 @@ // disconnect any open connection | ||
if(callback !== undefined) { | ||
mongodb.connect(_url, _options, function(err, db) { | ||
if (this.queryCache === null) { | ||
this.queryCache = new Cache(); | ||
} else { | ||
this.queryCache.reset(); | ||
} | ||
if (callback !== undefined) { | ||
mongodb.connect(_url, _options, function (err, db) { | ||
// flag we are done with the connection wait | ||
_connecting = false; | ||
if(err) { | ||
if (err) { | ||
return callback(err); | ||
@@ -90,5 +100,5 @@ } | ||
*/ | ||
disconnect: function(callback) { | ||
disconnect: function (callback) { | ||
if (this.db) { | ||
if(callback !== undefined) { | ||
if (callback !== undefined) { | ||
this.db.close(callback); | ||
@@ -102,2 +112,5 @@ } else { | ||
_connecting = false; | ||
if (this.queryCache !== null) { | ||
this.queryCache.reset(); | ||
} | ||
} | ||
@@ -135,3 +148,3 @@ }, | ||
*/ | ||
collection: function(collection_name, options, callback) { | ||
collection: function (collection_name, options, callback) { | ||
@@ -145,22 +158,20 @@ if (callback === undefined) { | ||
if(_connecting) { | ||
if (_connecting) { | ||
var odm = this; | ||
// delay this request since we are in transit to get a new connection | ||
setTimeout(function() { | ||
setTimeout(function () { | ||
odm.collection(collection_name, options, callback); | ||
}, 300); | ||
} | ||
else if(!_connected) { | ||
if(!_url) { | ||
} else if (!_connected) { | ||
if (!_url) { | ||
return callback('No Connection defined.'); | ||
} | ||
mongodb.connect(_url, _options, function(err, db) { | ||
mongodb.connect(_url, _options, function (err, db) { | ||
// flag we are done with the connection wait | ||
_connecting = false; | ||
if(err) { | ||
return callback(err); | ||
} | ||
if (err) { | ||
return callback(err); | ||
} | ||
@@ -171,3 +182,3 @@ self.db = db; | ||
self.db.collection(collection_name, options, function(err, collection) { | ||
self.db.collection(collection_name, options, function (err, collection) { | ||
if (!err) { | ||
@@ -186,3 +197,3 @@ _collections[collection_name] = collection; | ||
} else { | ||
self.db.collection(collection_name, options, function(err, collection) { | ||
self.db.collection(collection_name, options, function (err, collection) { | ||
if (!err) { | ||
@@ -216,3 +227,3 @@ _collections[collection_name] = collection; | ||
*/ | ||
document: function(mongoCollection, l2cache) { | ||
document: function (mongoCollection, l2cache) { | ||
@@ -223,7 +234,7 @@ var odm = this; | ||
var Model = function() { | ||
var Model = function () { | ||
throw new Error('Documents are read only and cannot be instantiated'); | ||
}; | ||
Model.findOne = function(query, fields, options, callback) { | ||
Model.findOne = function (query, fields, options, callback) { | ||
@@ -250,3 +261,3 @@ if (callback === undefined) { | ||
Model.find = function(query, fields, options, callback) { | ||
Model.find = function (query, fields, options, callback) { | ||
@@ -298,5 +309,5 @@ if (callback === undefined) { | ||
// verify if it is in cache | ||
if(l2cache) { | ||
if (l2cache) { | ||
var cachedDocuments = cache.get('all'); | ||
if(cachedDocuments !== undefined) { | ||
if (cachedDocuments !== undefined) { | ||
return callback(null, cachedDocuments); | ||
@@ -320,3 +331,3 @@ } | ||
if(l2cache) { | ||
if (l2cache) { | ||
cache.set('all', documentsLoaded); | ||
@@ -323,0 +334,0 @@ } |
203
lib/model.js
@@ -13,4 +13,2 @@ 'use strict'; | ||
var Cache = require('./cache'); | ||
var objectIdRegExp = new RegExp("^[0-9a-fA-F]{24}$"); | ||
@@ -543,3 +541,3 @@ | ||
callback = options; | ||
options = {}; | ||
// options = {}; | ||
} | ||
@@ -935,3 +933,3 @@ | ||
if (isEmptyProto(v)) { | ||
delete obj[key]; | ||
delete obj[key]; | ||
} else { | ||
@@ -942,3 +940,3 @@ // recurse | ||
if (isEmptyProto(v)) { | ||
delete obj[key]; | ||
delete obj[key]; | ||
} | ||
@@ -955,2 +953,66 @@ } | ||
/** | ||
* Helper caching function | ||
* | ||
* @param {Object} cache The Cache Manager Objects | ||
* @param {String} mongoCol Mongo Collection name | ||
* @param {String} field field used to index the cache | ||
* @param {String} value the value for the index key | ||
* @return {Object} | ||
*/ | ||
function isCached(cache, mongoCol, field, value) { | ||
if (cache !== undefined && cache !== null) { | ||
if (value instanceof ObjectID) { | ||
return cache.get(mongoCol + ':' + field + ':' + value.toHexString()); | ||
} | ||
return cache.get(mongoCol + ':' + field + ':' + value); | ||
} | ||
return undefined; | ||
} | ||
/** | ||
* Helper caching function | ||
* | ||
* @param {Object} cache The Cache Manager Objects | ||
* @param {String} mongoCol Mongo Collection name | ||
* @param {String} field field used to index the cache | ||
* @param {String} value the value for the index key | ||
* @param {Object} doc Document to store | ||
*/ | ||
function putToCache(cache, mongoCol, field, value, doc) { | ||
if (cache !== undefined && cache !== null) { | ||
if (value !== undefined && value !== null) { | ||
if (value instanceof ObjectID) { | ||
cache.set(mongoCol + ':' + field + ':' + value.toHexString(), doc); | ||
} | ||
} | ||
cache.set(mongoCol + ':' + field + ':' + value, doc); | ||
} | ||
} | ||
/** | ||
* Clears a cache entry for a specific model | ||
* @param {Object} cache The Cache Manager Objects | ||
* @param {String} mongoCol Mongo Collection name | ||
* @param {String[]} indexes for the model | ||
* @param {Model} model Model that triggered the cleanup | ||
*/ | ||
function purgeCache(cache, mongoCol, indexes, model) { | ||
if (cache !== undefined && cache !== null) { | ||
var _id = model._id; | ||
if (_id !== undefined && _id !== null) { | ||
if (_id instanceof ObjectID) { | ||
cache.del(mongoCol + ':' + '_id:' + _id.toHexString()); | ||
} | ||
} | ||
if (indexes !== undefined && indexes !== null) { | ||
var i; | ||
for (i = 0; i < indexes.length; i++) { | ||
cache.del(mongoCol + ':' + indexes[i] + ':' + model[indexes[i]]); | ||
} | ||
} | ||
cache.del(mongoCol + '::all'); | ||
} | ||
} | ||
/** | ||
* Creates a new Document Model class | ||
@@ -982,4 +1044,2 @@ * | ||
var cache = l2cache ? new Cache() : undefined; | ||
/** | ||
@@ -1049,24 +1109,2 @@ * @name Model | ||
// verify if it is in cache | ||
if (l2cache) { | ||
var _id = JSON.stringify(query); | ||
var cachedDocument = cache.get(_id); | ||
if (cachedDocument !== undefined) { | ||
// if we search for an Id and get null return right away | ||
if (cachedDocument === null) { | ||
return callback(null, null); | ||
} | ||
// special case (return direct document from mongoDB) | ||
if (directObject) { | ||
return callback(null, cachedDocument); | ||
} | ||
var model = new Model(cachedDocument, { deserialize: true }); | ||
return callback(null, model); | ||
} | ||
} | ||
odm.collection(mongoCollection, options, function (err, collection) { | ||
@@ -1135,3 +1173,3 @@ if (err) { | ||
if (l2cache) { | ||
var cachedDocument = cache.get(_id.toHexString()); | ||
var cachedDocument = isCached(odm.queryCache, mongoCollection, '_id', _id); | ||
@@ -1170,3 +1208,3 @@ if (cachedDocument !== undefined) { | ||
if (l2cache) { | ||
cache.set(_id.toHexString(), documentLoaded); | ||
putToCache(odm.queryCache, mongoCollection, '_id', _id, documentLoaded); | ||
} | ||
@@ -1304,3 +1342,3 @@ | ||
if (l2cache) { | ||
var cachedDocuments = cache.get('all'); | ||
var cachedDocuments = isCached(odm.queryCache, mongoCollection, '', 'all'); | ||
@@ -1346,3 +1384,3 @@ if (cachedDocuments !== undefined) { | ||
if (l2cache && pluck === undefined) { | ||
cache.set('all', documentsLoaded); | ||
putToCache(odm.queryCache, mongoCollection, '', 'all', documentsLoaded); | ||
} | ||
@@ -1462,2 +1500,94 @@ | ||
var indexFields = Object.keys(fieldOrSpec); | ||
if (indexFields.length === 1) { | ||
var field = indexFields[0]; | ||
// only create special finder if the index is not on a sub document | ||
if (field.indexOf('.') === -1) { | ||
// create special find with cache method | ||
var methodName = 'findBy' + field.substr(0, 1).toUpperCase() + field.substr(1); | ||
var valid = Model.internalSchema[field].$set; | ||
Model[methodName] = function (id, options, callback) { | ||
if (callback === undefined) { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (!mongoCollection) { | ||
return callback('Cannot ' + methodName + ' on embedded model'); | ||
} | ||
if (id === undefined) { | ||
return callback('undefined id'); | ||
} | ||
var _id; | ||
var directObject = extractOption('directObject', options); | ||
try { | ||
_id = valid(id); | ||
} catch (ex) { | ||
return callback(ex); | ||
} | ||
// verify if it is in cache | ||
if (l2cache) { | ||
var cachedDocument = isCached(odm.queryCache, mongoCollection, field, _id); | ||
if (cachedDocument !== undefined) { | ||
// if we search for an Id and get null return right away | ||
if (cachedDocument === null) { | ||
return callback(null, null); | ||
} | ||
// special case (return direct document from mongoDB) | ||
if (directObject) { | ||
return callback(null, cachedDocument); | ||
} | ||
var model = new Model(cachedDocument, { deserialize: true }); | ||
return callback(null, model); | ||
} | ||
} | ||
odm.collection(mongoCollection, options, function (err, collection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var query = {}; | ||
query[field] = _id; | ||
collection.findOne(query, options, function (err, documentLoaded) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (l2cache) { | ||
putToCache(odm.queryCache, mongoCollection, field, _id, documentLoaded); | ||
} | ||
// if we search for an Id and get null it should return right away | ||
if (documentLoaded === null) { | ||
return callback(null, null); | ||
} | ||
// special case (return direct document from mongoDB) | ||
if (directObject) { | ||
return callback(null, documentLoaded); | ||
} | ||
var model = new Model(documentLoaded, { deserialize: true }); | ||
callback(null, model); | ||
}); | ||
}); | ||
}; | ||
// add entry to the index keys | ||
Model.IndexKeys.push(field); | ||
} | ||
} | ||
odm.collection(mongoCollection, options, function (err, collection) { | ||
@@ -1543,3 +1673,3 @@ if (err) { | ||
if (l2cache) { | ||
cache.del(self._internalDocument._id.toHexString()); | ||
purgeCache(odm.queryCache, mongoCollection, Model.IndexKeys, self); | ||
} | ||
@@ -1578,3 +1708,3 @@ callback(null, self._internalDocument._id); | ||
if (l2cache) { | ||
cache.del(self._id.toHexString()); | ||
purgeCache(odm.queryCache, mongoCollection, Model.IndexKeys, self); | ||
} | ||
@@ -1615,3 +1745,3 @@ callback(err); | ||
if (l2cache) { | ||
cache.set(_id.toHexString(), documentLoaded); | ||
putToCache(odm.queryCache, mongoCollection, '_id', _id, documentLoaded); | ||
} | ||
@@ -1671,2 +1801,3 @@ | ||
Object.defineProperty(Model, 'Ref', {value: ObjectID}); | ||
Object.defineProperty(Model, 'IndexKeys', {value: []}); | ||
} | ||
@@ -1673,0 +1804,0 @@ |
@@ -8,3 +8,3 @@ { | ||
], | ||
"version": "0.0.15", | ||
"version": "0.0.16", | ||
"engines": { | ||
@@ -11,0 +11,0 @@ "node": ">=0.4.12" |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
95348
1977