UNPKG

joola.io.engine

Version:
197 lines (184 loc) 6.27 kB
/** * joola.io * * Copyright Joola Smart Solutions, Ltd. <info@joo.la> * * Licensed under GNU General Public License 3.0 or later. * Some rights reserved. See LICENSE, AUTHORS. * * @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+> */ var cache = function (joola, next) { joola.cache = {}; joola.cache.sweeperTimer = null; joola.cache.sweeperTimeout = 10 * 1000; joola.cache.redisCacheKey = "joola:cache"; joola.cache._start = function (joola, callback) { joola.cache.runSweeper(); return callback(); }; joola.cache._teardown = function (joola, next) { joola.cache.stopTimers(joola); return next(); }; joola.cache.stopTimers = function (joola) { clearTimeout(joola.cache.sweeperTimer); }; joola.cache.prepareDomain = function () { // until the redis module handles domains, we need to force the callback to be bound properly // https://github.com/mranney/node_redis/pull/310/files return { bind: function (callback) { return callback } } }; joola.cache.size = function (next) { var domain = joola.cache.prepareDomain(); joola.redis.client.hlen(joola.cache.redisCacheKey, domain.bind(function (err, count) { next(null, count); })); }; joola.cache.load = function (store, key, options, next) { if (typeof options == "function") { next = options; options = {} } var domain = joola.cache.prepareDomain(); joola.redis.client.hget(joola.cache.redisCacheKey + ':' + store, key, domain.bind(function (err, cacheObj) { if (err != null) { //joola.error(err); return next(new Error("Failed to get value from redis"), null, null, null, null); } try { cacheObj = JSON.parse(cacheObj); } catch (e) { } if (cacheObj == null) { if (typeof next == "function") { process.nextTick(function () { return next(new Error("Object not found"), null, null, null, null); }); } } else if (cacheObj.expireTimestamp >= new Date().getTime() || cacheObj.expireTimestamp == null) { cacheObj.readAt = new Date().getTime(); if (cacheObj.expireTimestamp != null && options.expireTimeMS) cacheObj.expireTimestamp = new Date().getTime() + options.expireTimeMS; joola.redis.client.hset(joola.cache.redisCacheKey, key, JSON.stringify(cacheObj), domain.bind(function () { if (typeof next == "function") { process.nextTick(function () { return next(null, cacheObj.value, cacheObj.expireTimestamp, cacheObj.createdAt, cacheObj.readAt); }); } })); } else { if (typeof next == "function") { process.nextTick(function () { return next(new Error("Object expired"), null, null, null, null); }); } } })); }; joola.cache.destroy = function (key, next) { var domain = joola.cache.prepareDomain(); joola.redis.client.hdel(joola.cache.redisCacheKey, key, domain.bind(function (err, count) { //joola.stats.increment("cache:cachedObjects", -1 ); if (err != null) { joola.logger.error(err); } var resp = true; if (count != 1) { resp = false; } if (typeof next == "function") { process.nextTick(function () { next(null, resp); }); } })); }; joola.cache.sweeper = function (next) { var domain = joola.cache.prepareDomain(); joola.redis.client.hkeys(joola.cache.redisCacheKey, domain.bind(function (err, keys) { var started = 0; var sweepedKeys = []; keys.forEach(function (key) { started++; joola.redis.client.hget(joola.cache.redisCacheKey, key, domain.bind(function (err, cacheObj) { if (err != null) { joola.logger.error(err); } try { JSON.parse(cacheObj); } catch (e) { } if (cacheObj != null) { if (cacheObj.expireTimestamp != null && cacheObj.expireTimestamp < new Date().getTime()) { joola.redis.client.hdel(joola.cache.redisCacheKey, key, domain.bind(function (err) { sweepedKeys.push(key); started--; if (started == 0 && typeof next == "function") { next(err, sweepedKeys); } })); } else { started--; if (started == 0 && typeof next == "function") { next(err, sweepedKeys); } } } else { started--; if (started == 0 && typeof next == "function") { next(err, sweepedKeys); } } })); }); if (keys.length == 0 && typeof next == "function") { next(err, sweepedKeys); } })); }; joola.cache.save = function (store, key, value, expireTimeMS, next) { var domain = joola.cache.prepareDomain(); if (typeof expireTimeMS == "function" && typeof next == "undefined") { next = expireTimeMS; expireTimeMS = null; } if (expireTimeMS != null) { var expireTimestamp = new Date().getTime() + expireTimeMS; } else { expireTimestamp = null; } var cacheObj = { value: value, expireTimestamp: expireTimestamp, createdAt: new Date().getTime(), readAt: null }; joola.redis.client.hset(joola.cache.redisCacheKey + ':' + store, key, JSON.stringify(cacheObj), domain.bind(function () { if (typeof next == "function") { process.nextTick(function () { next(null, true); }); } })); }; joola.cache.runSweeper = function () { clearTimeout(joola.cache.sweeperTimer); joola.cache.sweeper(function (err, sweepedKeys) { if (sweepedKeys.length > 0) { joola.logger.info("cleaned " + sweepedKeys.length + " expired cache keys", "debug"); } if (joola.running) { joola.cache.sweeperTimer = setTimeout(joola.cache.runSweeper, joola.cache.sweeperTimeout, joola); } }); }; next(); }; ///////////////////////////////////////////////////////////////////// // exports exports.cache = cache;