Plato on Github
Report Home
lib/file_loader.js
Maintainability
72.97
Lines of code
214
Difficulty
39.87
Estimated Errors
1.36
Function weight
By Complexity
By SLOC
// Generated by CoffeeScript 1.6.2 /* This method will load file, cache result and so on */ (function() { var FileLoader, LRU, XXHash, async, fs, path, rejectOnInvalidFilenameType, _; fs = require('fs'); path = require('path'); _ = require('lodash'); async = require('async'); XXHash = require('xxhash'); LRU = require('lru-cache'); /* Checker method decorator */ rejectOnInvalidFilenameType = function(methodBody) { return function(filename, cb) { if (!_.isString(filename)) { return cb(TypeError("must be called with filename as String, but got:\n|filename| = |" + filename + "|")); } return methodBody.call(this, filename, cb); }; }; FileLoader = (function() { var HASH_SALT, MAX_AGE; HASH_SALT = 0xCAFEBABE; MAX_AGE = 1000 * 60 * 60 * 10; function FileLoader(_options_) { this._options_ = _options_ != null ? _options_ : {}; this._file_cache_ = LRU({ max: 1000, maxAge: MAX_AGE }); this._file_in_process_ = {}; } /* This method reset all caches */ FileLoader.prototype.resetCaches = function() { this._file_cache_.reset(); this._file_in_process_ = {}; return null; }; /* This method try to get file content from hash or give up and read it from disk */ FileLoader.prototype.getFileContent = rejectOnInvalidFilenameType(function(filename, cb) { return this.getFileWithMeta(filename, function(err, data) { if (err) { return cb(err); } return cb(null, data.content); }); }); /* This method, get all - content and meta for filename */ FileLoader.prototype.getFileWithMeta = rejectOnInvalidFilenameType(function(filename, cb) { var cached_file, lazy_fn, _this = this; if (!this._file_cache_.has(filename)) { if (this._file_in_process_[filename]) { lazy_fn = function() { return _this.getFileWithMeta(filename, cb); }; return setTimeout(lazy_fn, 0); } else { this._file_in_process_[filename] = true; return this._loadAllFileData(filename, function(err, data) { _this._file_in_process_[filename] = false; if (err) { return cb(err); } _this._file_cache_.set(filename, data); return cb(null, data); }); } } else { cached_file = this._file_cache_.get(filename); return this.readFileMeta(filename, function(err, meta) { if (err) { return cb(err); } if (cached_file.meta.mtime === meta.mtime) { return cb(null, cached_file); } else { return _this.readFileDigest(filename, function(err, digest) { if (err) { return cb(err); } if (cached_file.digest === digest) { cached_file.meta = meta; _this._file_cache_.set(filename, cached_file); return cb(null, cached_file); } else { return _this.readFile(filename, function(err, content) { var new_file; if (err) { return cb(err); } new_file = { meta: meta, digest: digest, content: content }; _this._file_cache_.set(filename, new_file); return cb(null, new_file); }); } }); } }); } }); /* This internal method to load all file data */ FileLoader.prototype._loadAllFileData = function(filename, step_cb) { var _this = this; return async.parallel({ meta: function(parallel_cb) { return _this.readFileMeta(filename, parallel_cb); }, digest: function(parallel_cb) { return _this.readFileDigest(filename, parallel_cb); }, content: function(parallel_cb) { return _this.readFile(filename, parallel_cb); } }, step_cb); }; /* This method just read a file, from disk */ FileLoader.prototype.readFile = rejectOnInvalidFilenameType(function(filename, cb) { return fs.readFile(filename, 'utf8', function(err, data) { if (err) { return cb(err); } return cb(null, data); }); }); /* This method read all file meta */ FileLoader.prototype.readFileMeta = rejectOnInvalidFilenameType(function(filename, cb) { return fs.stat(filename, function(err, stats) { if (err) { return cb(err); } return cb(null, { mtime: +stats.mtime }); }); }); /* This method generate digest for file content */ FileLoader.prototype.readFileDigest = rejectOnInvalidFilenameType(function(filename, cb) { var hasher, stream; hasher = new XXHash(HASH_SALT); stream = fs.createReadStream(filename); stream.on('data', function(data) { return hasher.update(data); }); stream.on('error', function(err) { return cb(err); }); return stream.on('end', function() { return cb(null, hasher.digest()); }); }); return FileLoader; })(); module.exports = FileLoader; }).call(this);