Skip to content

Instantly share code, notes, and snippets.

@cappsool
Created October 15, 2018 14:19
Show Gist options
  • Save cappsool/7d2de0531e156ef942d778a426248b9e to your computer and use it in GitHub Desktop.
Save cappsool/7d2de0531e156ef942d778a426248b9e to your computer and use it in GitHub Desktop.
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