-
-
Save cappsool/7d2de0531e156ef942d778a426248b9e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var mongoose = require('mongoose'); | |
var moment = require('moment'); | |
var config = require('../../config/environment'); | |
// setup Redis client that supports both local machine with redis-mock and production server | |
var redis = null; | |
var client; | |
if (! redis) { | |
if (process.env.NODE_ENV != 'development') { | |
redis = require('redis'); | |
client = redis.createClient(6379, config.redisEndpoint, {no_ready_check: false}); | |
client.on('error', function (e) { | |
console.log("Redis Client Error" + e.toString()); | |
client.quit(); | |
}); | |
} | |
else { | |
redis = require("redis-mock"); | |
client = redis.createClient(); | |
} | |
} | |
// counting cache hits and cache misses - also use Redis for this | |
function internalInc(k) { | |
setTimeout(function(){ | |
var key = "0" + config.redisPrefix + k + moment().utc().format('MM-DD-YYYY'); | |
var multi = client.multi(); | |
multi.expire(key, 24 * 60 * 60); | |
multi.incr(key); | |
multi.exec(function (err, data) { | |
if (err) { console.log("Redis error", err) }; | |
}) | |
},0); | |
} | |
function incMongoCacheHits(){ | |
var k = "mongoCacheHits"; | |
internalInc(k); | |
}; | |
function incMongoCacheMiss(){ | |
var k = "mongoCacheMiss"; | |
internalInc(k); | |
}; | |
var redisKey = function(table, field, value){ | |
return "0" + config.redisPrefix + "_MC_" + table.collection.collectionName + "_" + field + "_" + value; | |
} | |
// call this when a mongo object is saved in order to remove it from the cache. It will be lazy-loaded when required | |
var touchObject = function (table, fields, cb) { | |
var multi = client.multi(); | |
for (var k in fields) { | |
var key = redisKey(table, k, fields[k]); | |
multi.del(key); | |
} | |
multi.exec(function(err,val){ | |
if(err) return cb(err); | |
return cb(null); | |
}); | |
} | |
// get a single MongoDB item by field and value | |
// table - mongoose collection definition | |
// will search the item in Redis and if not found will be loaded from MongoDB, saved to redis, and returned to the requester | |
// note: the returned object is a clone and cannot be eddited or saved to MongoDB. | |
// example: | |
// MongoCache.getObjectByField(Customer, MongoCache.ID, customerId, function (err, item) { ... }); | |
var getObjectByField = function(table, field, value, cb){ | |
var key = redisKey(table, field, value); | |
client.get(key,function(err,val){ | |
if(err) return cb(err); | |
if (val == null) { | |
console.log("MongoCacheMiss " + key); | |
incMongoCacheMiss(); | |
var query; | |
if (!field || field == idField) { | |
query = table.findById(value); | |
} else { | |
var filter = {} | |
filter[field] = value; | |
query = table.findOne(filter) | |
} | |
query.lean().exec(function(err, item) { | |
if (err) return cb(err); | |
client.setex(key, 60*60, JSON.stringify(item), function (err) { | |
if (err) return cb(err); | |
return cb(null, item); | |
}); | |
}); | |
} else { | |
try{ | |
var ret = JSON.parse(val); | |
incMongoCacheHits(); | |
} | |
catch(e){ | |
return cb("redis_mongoCache_get---" + key + " " + e + " " +val); | |
} | |
return cb(null,ret); | |
} | |
}); | |
} | |
var idField = "_id"; | |
var MongoCache = { | |
touchObject: touchObject, | |
getObjectByField: getObjectByField, | |
ID : idField | |
}; | |
module.exports = MongoCache; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment