cache-storage
Version:
[ABANDONED] Advanced cache storage for node js
397 lines (372 loc) • 12.8 kB
JavaScript
// Generated by CoffeeScript 1.6.3
(function() {
var BaseStorage, Cache, Storage, async, isWindow, moment, path, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
isWindow = typeof window === 'undefined' ? false : true;
if (!isWindow) {
path = require('path');
}
BaseStorage = require('../Storage');
moment = require('moment');
Cache = require('../../Cache');
async = require('async');
Storage = (function(_super) {
__extends(Storage, _super);
function Storage() {
_ref = Storage.__super__.constructor.apply(this, arguments);
return _ref;
}
Storage.prototype.async = true;
Storage.prototype.read = function(key, fn) {
var _this = this;
return this.getData(function(err, data) {
if (err) {
return fn(err, null);
} else if (typeof data[key] === 'undefined') {
return fn(null, null);
} else {
return _this.findMeta(key, function(err, meta) {
if (err) {
return fn(err, null);
} else {
return _this.verify(meta, function(err, state) {
if (err) {
return fn(err, null);
} else if (state) {
return fn(null, data[key]);
} else {
return _this.remove(key, function(err) {
if (err) {
return fn(err, null);
} else {
return fn(null, null);
}
});
}
});
}
});
}
});
};
Storage.prototype.write = function(key, data, dependencies, fn) {
var _this = this;
if (dependencies == null) {
dependencies = {};
}
return this.getData(function(err, all) {
if (err) {
return fn(err);
} else {
all[key] = data;
return _this.getMeta(function(err, meta) {
if (err) {
return fn(err);
} else {
meta[key] = dependencies;
return _this.writeData(all, meta, fn);
}
});
}
});
};
Storage.prototype.remove = function(key, fn) {
var _this = this;
return this.getData(function(err, data) {
if (err) {
return fn(err);
} else {
return _this.getMeta(function(err, meta) {
if (err) {
return fn(err);
} else {
if (typeof data[key] !== 'undefined') {
delete data[key];
delete meta[key];
}
return _this.writeData(data, meta, fn);
}
});
}
});
};
Storage.prototype.removeAll = function(fn) {
return this.writeData({}, {}, fn);
};
Storage.prototype.clean = function(conditions, fn) {
var keys, removeKeys, type, typeFn,
_this = this;
typeFn = Object.prototype.toString;
type = typeFn.call(conditions);
if (conditions === Cache.ALL) {
this.removeAll(fn);
} else if (type === '[object Object]') {
if (typeof conditions[Cache.TAGS] === 'undefined') {
conditions[Cache.TAGS] = [];
}
if (typeFn(conditions[Cache.TAGS]) === '[object String]') {
conditions[Cache.TAGS] = [conditions[Cache.TAGS]];
}
removeKeys = function(keys) {
return async.eachSeries(keys, function(key, cb) {
return _this.remove(key, function(err) {
return cb(err);
});
}, function(err) {
return fn(err);
});
};
keys = [];
async.eachSeries(conditions[Cache.TAGS], function(tag, cb) {
return _this.findKeysByTag(tag, function(err, _keys) {
keys = keys.concat(_keys);
return cb(err);
});
}, function(err) {
if (err) {
return fn(err);
} else if (typeof conditions[Cache.PRIORITY] === 'undefined') {
return removeKeys(keys);
} else {
return _this.findKeysByPriority(conditions[Cache.PRIORITY], function(err, _keys) {
if (err) {
return fn(err);
} else {
keys = keys.concat(_keys);
return removeKeys(keys);
}
});
}
});
} else {
fn(null);
}
return this;
};
Storage.prototype.findMeta = function(key, fn) {
return this.getMeta(function(err, meta) {
if (err) {
return fn(err, null);
} else if (typeof meta[key] !== 'undefined') {
return fn(null, meta[key]);
} else {
return fn(null, null);
}
});
};
Storage.prototype.findKeysByTag = function(tag, fn) {
return this.getMeta(function(err, metas) {
var key, meta, result;
if (err) {
return fn(err, null);
} else {
result = [];
for (key in metas) {
meta = metas[key];
if (typeof meta[Cache.TAGS] !== 'undefined' && meta[Cache.TAGS].indexOf(tag) !== -1) {
result.push(key);
}
}
return fn(null, result);
}
});
};
Storage.prototype.findKeysByPriority = function(priority, fn) {
return this.getMeta(function(err, metas) {
var key, meta, result;
if (err) {
return fn(err, null);
} else {
result = [];
for (key in metas) {
meta = metas[key];
if (typeof meta[Cache.PRIORITY] !== 'undefined' && meta[Cache.PRIORITY] <= priority) {
result.push(key);
}
}
return fn(null, result);
}
});
};
Storage.prototype.verify = function(meta, fn) {
var typefn,
_this = this;
typefn = Object.prototype.toString;
if (typefn.call(meta) === '[object Object]') {
if (typeof meta[Cache.EXPIRE] !== 'undefined') {
if (moment().valueOf() >= meta[Cache.EXPIRE]) {
fn(null, false);
return null;
}
}
if (typeof meta[Cache.ITEMS] === 'undefined') {
meta[Cache.ITEMS] = [];
}
return async.eachSeries(meta[Cache.ITEMS], function(item, cb) {
return _this.findMeta(item, function(err, meta) {
if (err) {
fn(err, null);
return cb(new Error('Fake error'));
} else if (meta === null) {
fn(null, false);
return cb(new Error('Fake error'));
} else if (meta !== null) {
return _this.verify(meta, function(err, state) {
if (err) {
fn(err, null);
return cb(new Error('Fake error'));
} else if (state === false) {
fn(null, false);
return cb(new Error('Fake error'));
} else {
return cb();
}
});
} else {
return cb();
}
});
}, function(err) {
var file, files, mtime, time, _ref1, _ref2, _ref3;
if (!err) {
if (typeof meta[Cache.FILES] === 'undefined') {
meta[Cache.FILES] = [];
}
_this.checkFilesSupport();
if (isWindow) {
_ref1 = meta[Cache.FILES];
for (file in _ref1) {
time = _ref1[file];
mtime = window.require.getStats(file).mtime;
if (mtime === null) {
throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
}
if (window.require.getStats(file).mtime.getTime() !== time) {
fn(null, false);
return null;
}
}
return fn(null, true);
} else {
files = [];
_ref2 = meta[Cache.FILES];
for (file in _ref2) {
time = _ref2[file];
_ref3 = meta[Cache.FILES];
for (file in _ref3) {
time = _ref3[file];
files.push({
file: file,
time: time
});
}
}
return async.eachSeries(files, function(item, cb) {
return Cache.getFs().stat(item.file, function(err, stats) {
if (err) {
return cb(err);
} else {
if ((new Date(stats.mtime)).getTime() !== item.time) {
fn(null, false);
return cb(new Error('Fake error'));
} else {
return cb();
}
}
});
}, function(err) {
if (err && err.message === 'Fake error') {
} else if (err) {
return fn(err, null);
} else {
return fn(null, true);
}
});
}
}
});
} else {
return fn(null, true);
}
};
Storage.prototype.parseDependencies = function(dependencies, fn) {
var file, files, item, mtime, result, time, typefn, _i, _j, _len, _len1, _ref1, _ref2;
typefn = Object.prototype.toString;
result = {};
if (typefn.call(dependencies) === '[object Object]') {
if (typeof dependencies[Cache.EXPIRE] !== 'undefined') {
switch (typefn.call(dependencies[Cache.EXPIRE])) {
case '[object String]':
time = moment(dependencies[Cache.EXPIRE], Cache.TIME_FORMAT);
break;
case '[object Object]':
time = moment().add(dependencies[Cache.EXPIRE]);
break;
default:
throw new Error('Expire format is not valid');
}
result[Cache.EXPIRE] = time.valueOf();
}
if (typeof dependencies[Cache.ITEMS] !== 'undefined') {
result[Cache.ITEMS] = [];
_ref1 = dependencies[Cache.ITEMS];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
item = _ref1[_i];
result[Cache.ITEMS].push(this.cache.generateKey(item));
}
}
if (typeof dependencies[Cache.PRIORITY] !== 'undefined') {
result[Cache.PRIORITY] = dependencies[Cache.PRIORITY];
}
if (typeof dependencies[Cache.TAGS] !== 'undefined') {
result[Cache.TAGS] = dependencies[Cache.TAGS];
}
if (typeof dependencies[Cache.FILES] !== 'undefined') {
this.checkFilesSupport();
files = {};
if (isWindow) {
_ref2 = dependencies[Cache.FILES];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
file = _ref2[_j];
mtime = window.require.getStats(file).mtime;
if (mtime === null) {
throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
}
file = window.require.resolve(file);
files[file] = mtime.getTime();
}
result[Cache.FILES] = files;
fn(null, result);
} else {
async.eachSeries(dependencies[Cache.FILES], function(file, cb) {
file = path.resolve(file);
return Cache.getFs().stat(file, function(err, stats) {
if (err) {
return cb(err);
} else {
files[file] = (new Date(stats.mtime)).getTime();
return cb();
}
});
}, function(err) {
if (err) {
return fn(err, null);
} else {
result[Cache.FILES] = files;
return fn(null, result);
}
});
}
return result[Cache.FILES] = files;
} else {
return fn(null, result);
}
} else {
return fn(null, result);
}
};
return Storage;
})(BaseStorage);
module.exports = Storage;
}).call(this);