From 95f708628a376a46abe1418071ae3cc2623606ab Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Tue, 18 Aug 2015 16:09:11 -0700 Subject: [PATCH 1/7] Allow Filter To Persist For Warm Boot This incorporates the ideas in https://github.com/stefanpenner/broccoli-persistent-filter and to make optional via a persist flag. This currently does not work on windows however it is not detrimental to the end user as it is opt in. --- index.js | 80 +++++++++++++++++++++++++++----- package.json | 3 ++ test/fixtures/directory/.gitkeep | 0 test/key-for-file-tests.js | 2 +- test/test.js | 56 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 13 deletions(-) delete mode 100644 test/fixtures/directory/.gitkeep diff --git a/index.js b/index.js index c92a36f..e014924 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,9 @@ var copyDereferenceSync = require('copy-dereference').sync; var Cache = require('./lib/cache'); var debugGenerator = require('debug'); var keyForFile = require('./lib/key-for-file'); +var PersistentCache = require('async-disk-cache'); +var hashForDep = require('hash-for-dep'); +var md5Hex = require('md5-hex'); module.exports = Filter; @@ -43,6 +46,16 @@ function Filter(inputTree, options) { this.inputEncoding = options.inputEncoding; if (options.outputEncoding != null) this.outputEncoding = options.outputEncoding; + if (options.persist) { + if (/^win/.test(process.platform)) { + console.log('Unfortunately persistent cache is currently not available on windows based systems.'); + } else { + this.persistent = options.persist; + this._peristentCache = new PersistentCache(this.cacheKey(), { + compression: 'deflate' + }); + } + } } this._cache = new Cache(); @@ -75,6 +88,36 @@ Filter.prototype.build = function build() { }); }; +/* + * @private + * + * + * @method cachKey + * @return {String} this filters top-level cache key + */ +Filter.prototype.cacheKey = function() { + return hashForDep(this.baseDir()); +}; + +/* @public + * + * @method baseDir + * @returns {String} absolute path to the root of the filter... + */ +Filter.prototype.baseDir = function() { + throw Error('Filter must implement prototype.baseDir'); +}; + +/* + * @public + * + * @method cacheKeyProcessString + * @return {String} this filters top-level cache key + */ +Filter.prototype.cacheKeyProcessString = function(string) { + return md5Hex(string); +}; + Filter.prototype.canProcessFile = function canProcessFile(relativePath) { return !!this.getDestFilePath(relativePath); @@ -160,19 +203,32 @@ Filter.prototype.processFile = if (outputEncoding === void 0) outputEncoding = 'utf8'; var contents = fs.readFileSync( srcDir + '/' + relativePath, { encoding: inputEncoding }); + var promise; - return Promise.resolve(this.processString(contents, relativePath)). - then(function asyncOutputFilteredFile(outputString) { - var outputPath = self.getDestFilePath(relativePath); - if (outputPath == null) { - throw new Error('canProcessFile("' + relativePath + '") is true, but getDestFilePath("' + relativePath + '") is null'); - } - outputPath = destDir + '/' + outputPath; - mkdirp.sync(path.dirname(outputPath)); - fs.writeFileSync(outputPath, outputString, { - encoding: outputEncoding - }); - }); + if (this.persistent) { + var key = this.cacheKeyProcessString(contents, relativePath); + promise = this._peristentCache.get(key).then(function(entry) { + return entry.isCached ? entry.value : self.processString(contents, relativePath); + }); + } else { + promise = Promise.resolve(this.processString(contents, relativePath)); + } + + return promise.then(function asyncOutputFilteredFile(outputString) { + var outputPath = self.getDestFilePath(relativePath); + if (outputPath == null) { + throw new Error('canProcessFile("' + relativePath + '") is true, but getDestFilePath("' + relativePath + '") is null'); + } + outputPath = destDir + '/' + outputPath; + mkdirp.sync(path.dirname(outputPath)); + fs.writeFileSync(outputPath, outputString, { + encoding: outputEncoding + }); + + if (self.persistent) { + return self._peristentCache.set(key, outputString); + } + }); }; Filter.prototype.processString = diff --git a/package.json b/package.json index 2bbedf0..114049c 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,13 @@ "cache" ], "dependencies": { + "async-disk-cache": "^1.0.0", "broccoli-kitchen-sink-helpers": "^0.2.7", "broccoli-plugin": "^1.0.0", "copy-dereference": "^1.0.0", "debug": "^2.2.0", + "hash-for-dep": "0.0.3", + "md5-hex": "^1.0.2", "mkdirp": "^0.5.1", "promise-map-series": "^0.2.1", "rsvp": "^3.0.18", diff --git a/test/fixtures/directory/.gitkeep b/test/fixtures/directory/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/key-for-file-tests.js b/test/key-for-file-tests.js index 4b644fd..b73933d 100644 --- a/test/key-for-file-tests.js +++ b/test/key-for-file-tests.js @@ -8,7 +8,7 @@ describe('keyForFile', function () { describe('when given a path to a directory', function () { it('throws an error', function () { expect(function () { - keyForFile('./test/fixtures/directory'); + keyForFile('./test/fixtures/dir'); }).to.throw(/cannot diff directory/i); }); }); diff --git a/test/test.js b/test/test.js index 61217ec..e6785a7 100644 --- a/test/test.js +++ b/test/test.js @@ -45,6 +45,10 @@ ReplaceFilter.prototype.processString = function(contents, relativePath) { return result; }; +ReplaceFilter.prototype.baseDir = function() { + return '../'; +}; + function IncompleteFilter(inputTree, options) { if (!this) return new IncompleteFilter(inputTree, options); Filter.call(this, inputTree, options); @@ -290,6 +294,58 @@ describe('Filter', function() { to.equal('utf8'); }); + if (!/^win/.test(process.platform)) { + describe('persistent cache', function() { + var f; + function F(inputTree, options) { Filter.call(this, inputTree, options); } + inherits(F, Filter); + F.prototype.baseDir = function() { + return '../'; + }; + + beforeEach(function() { + f = new F(fixturePath, { persist: true }); + }); + + it('cache is initialized', function() { + expect(f._peristentCache).to.be.ok; + }); + + it('default `baseDir` implementation throws an Unimplemented Exception', function() { + function F(inputTree, options) { Filter.call(this, inputTree, options); } + inherits(F, Filter); + expect(function() { + new F(fixturePath, { persist: true }); + }).to.throw(/Filter must implement prototype.baseDir/); + }); + + it('`cacheKeyProcessString` return correct first level file cache', function() { + expect(f.cacheKeyProcessString('foo-bar-baz', 'relative-path')).to.eql('4c43793687f9a7170a9149ad391cbf70'); + }); + + it('filter properly reads file tree', function() { + var builder = makeBuilder(ReplaceFilter, fixturePath, function(awk) { + return awk; + }); + + return builder('dir', { + persist: true, + glob: '**/*.md', + search: 'dogs', + replace: 'cats' + }).then(function(results) { + expect(results.files).to.deep.eql([ + 'a/', + 'a/README.md', + 'a/bar/', + 'a/bar/bar.js', + 'a/foo.js' + ]); + }); + }); + }); + } + describe('processFile', function() { beforeEach(function() { sinon.spy(fs, 'mkdirSync'); From d98f019af21fd4e3687595a2f1b8e92c590d25b7 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 08:02:15 -0700 Subject: [PATCH 2/7] Add details to the README --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README.md b/README.md index 786ffd4..0ef19f3 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,48 @@ var node = new Awk('docs', 'ES6', 'ECMAScript 2015'); module.exports = node; ``` +## Persistent Cache + +__Note: This feature is experimental and is only available on Unix based systems.__ + +Adding persist flag allows a subclass to persist state across restarts. This exists to mitigate the upfront cost of some more expensive transforms on warm boot. __It does not aim to improve incremental build performance, if it does, it should indicate something is wrong with the filter or input filter in question.__ + +### How does it work? + +It does so but establishing a 2 layer file cache. The first layer, is the entire bucket. +The second, `cacheKeyProcessString` is a per file cache key. + +Together, these two layers should provide the right balance of speed and sensibility. + +The bucket level cacheKey must be stable but also never become stale. If the key is not +stable, state between restarts will be lost and performance will suffer. On the flip-side, +if the cacheKey becomes stale changes may not be correctly reflected. + +It is configured by subclassing and refining `cacheKey` method. A good key here, is +likely the name of the plugin, its version and the actual versions of its dependencies. + +```js +Subclass.prototype.cacheKey = function() { + return md5(Filter.prototype.call(this) + inputOptionsChecksum + dependencyVersionChecksum); +} +``` + +The second key, represents the contents of the file. Typically the base-class's functionality +is sufficient, as it merely generates a checksum of the file contents. If for some reason this +is not sufficient, it can be re-configured via subclassing. + +```js +Subclass.prototype.cacheKeyProcessString = function(string, relativePath) { + return superAwesomeDigest(string); +} +``` + +It is recommended that persistent re-builds is opt-in by the consumer as it does not currently work on all systems. + +```js +var myTree = new SomePlugin('lib', { persist: true }); +``` + ## FAQ ### Upgrading from 0.1.x to 1.x From ea86689890dceaefe771b327446e6c52e69d74af Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 11:46:04 -0700 Subject: [PATCH 3/7] Refactor to use strategy pattern This removes majority of the branching and instead uses a strategy pattern. --- index.js | 62 +++++++++++------------------------- lib/processor.js | 21 ++++++++++++ lib/strategies/default.js | 13 ++++++++ lib/strategies/persistent.js | 52 ++++++++++++++++++++++++++++++ test/test.js | 4 +-- 5 files changed, 106 insertions(+), 46 deletions(-) create mode 100644 lib/processor.js create mode 100644 lib/strategies/default.js create mode 100644 lib/strategies/persistent.js diff --git a/index.js b/index.js index e014924..1a0c296 100644 --- a/index.js +++ b/index.js @@ -16,9 +16,12 @@ var keyForFile = require('./lib/key-for-file'); var PersistentCache = require('async-disk-cache'); var hashForDep = require('hash-for-dep'); var md5Hex = require('md5-hex'); +var Processor = require('./lib/processor'); +var defaultProccessor = require('./lib/strategies/default'); module.exports = Filter; + Filter.prototype = Object.create(Plugin.prototype); Filter.prototype.constructor = Filter; function Filter(inputTree, options) { @@ -36,6 +39,9 @@ function Filter(inputTree, options) { Plugin.call(this, [inputTree]); + this.processor = new Processor(); + this.processor.setStrategy(defaultProccessor); + /* Destructuring assignment in node 0.12.2 would be really handy for this! */ if (options) { if (options.extensions != null) @@ -48,16 +54,15 @@ function Filter(inputTree, options) { this.outputEncoding = options.outputEncoding; if (options.persist) { if (/^win/.test(process.platform)) { - console.log('Unfortunately persistent cache is currently not available on windows based systems.'); + console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); } else { - this.persistent = options.persist; - this._peristentCache = new PersistentCache(this.cacheKey(), { - compression: 'deflate' - }); + this.processor.setStrategy(require('./lib/strategies/persistent')); } } } + this.processor.init(this); + this._cache = new Cache(); this._canProcessCache = Object.create(null); this._destFilePathCache = Object.create(null); @@ -88,17 +93,6 @@ Filter.prototype.build = function build() { }); }; -/* - * @private - * - * - * @method cachKey - * @return {String} this filters top-level cache key - */ -Filter.prototype.cacheKey = function() { - return hashForDep(this.baseDir()); -}; - /* @public * * @method baseDir @@ -108,28 +102,18 @@ Filter.prototype.baseDir = function() { throw Error('Filter must implement prototype.baseDir'); }; -/* - * @public - * - * @method cacheKeyProcessString - * @return {String} this filters top-level cache key - */ -Filter.prototype.cacheKeyProcessString = function(string) { - return md5Hex(string); -}; - Filter.prototype.canProcessFile = function canProcessFile(relativePath) { return !!this.getDestFilePath(relativePath); }; Filter.prototype.getDestFilePath = function getDestFilePath(relativePath) { - if (this.extensions == null) return relativePath; + if (this.extensions === null) return relativePath; for (var i = 0, ii = this.extensions.length; i < ii; ++i) { var ext = this.extensions[i]; if (relativePath.slice(-ext.length - 1) === '.' + ext) { - if (this.targetExtension != null) { + if (this.targetExtension !== null) { relativePath = relativePath.slice(0, -ext.length) + this.targetExtension; } @@ -137,7 +121,7 @@ Filter.prototype.getDestFilePath = function getDestFilePath(relativePath) { } } return null; -} +}; Filter.prototype.processAndCacheFile = function processAndCacheFile(srcDir, destDir, relativePath) { @@ -172,7 +156,7 @@ Filter.prototype.processAndCacheFile = e.file = relativePath; e.treeDir = srcDir; throw e; - }) + }); function copyToCache() { var entry = { @@ -203,18 +187,10 @@ Filter.prototype.processFile = if (outputEncoding === void 0) outputEncoding = 'utf8'; var contents = fs.readFileSync( srcDir + '/' + relativePath, { encoding: inputEncoding }); - var promise; - if (this.persistent) { - var key = this.cacheKeyProcessString(contents, relativePath); - promise = this._peristentCache.get(key).then(function(entry) { - return entry.isCached ? entry.value : self.processString(contents, relativePath); - }); - } else { - promise = Promise.resolve(this.processString(contents, relativePath)); - } - - return promise.then(function asyncOutputFilteredFile(outputString) { + return this.processor.processString(this, contents, relativePath).then( + function asyncOutputFilteredFile(result) { + var outputString = result.string; var outputPath = self.getDestFilePath(relativePath); if (outputPath == null) { throw new Error('canProcessFile("' + relativePath + '") is true, but getDestFilePath("' + relativePath + '") is null'); @@ -225,9 +201,7 @@ Filter.prototype.processFile = encoding: outputEncoding }); - if (self.persistent) { - return self._peristentCache.set(key, outputString); - } + return self.processor.done(self, result); }); }; diff --git a/lib/processor.js b/lib/processor.js new file mode 100644 index 0000000..6207713 --- /dev/null +++ b/lib/processor.js @@ -0,0 +1,21 @@ +function Processor() { + this.processor = {}; +} + +Processor.prototype.setStrategy = function(stringProcessor) { + this.processor = stringProcessor; +}; + +Processor.prototype.init = function(ctx) { + this.processor.init(ctx); +}; + +Processor.prototype.processString = function(ctx, contents, relativePath) { + return this.processor.processString(ctx, contents, relativePath); +}; + +Processor.prototype.done = function(ctx, result) { + return this.processor.done(ctx, result); +}; + +module.exports = Processor; diff --git a/lib/strategies/default.js b/lib/strategies/default.js new file mode 100644 index 0000000..9c26a45 --- /dev/null +++ b/lib/strategies/default.js @@ -0,0 +1,13 @@ +var Promise = require('rsvp').Promise; + +module.exports = { + init: function() {}, + + processString: function(ctx, contents, relativePath) { + return Promise.resolve({ string: ctx.processString(contents, relativePath) }); + }, + + done: function(ctx) { + return Promise.resolve(ctx.outputPath); + } +}; diff --git a/lib/strategies/persistent.js b/lib/strategies/persistent.js new file mode 100644 index 0000000..37fe74c --- /dev/null +++ b/lib/strategies/persistent.js @@ -0,0 +1,52 @@ +'use strict'; + +var md5Hex = require('md5-hex'); +var PersistentCache = require('async-disk-cache'); +var hashForDep = require('hash-for-dep'); + +module.exports = { + + _peristentCache: {}, + + init: function(ctx) { + if (/^win/.test(process.platform)) { + console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); + } + this._peristentCache = new PersistentCache(this.cacheKey(ctx), { + compression: 'deflate' + }); + }, + + cacheKey: function(ctx) { + return hashForDep(ctx.baseDir()); + }, + + cacheKeyProcessString: function(string) { + return md5Hex(string); + }, + + processString: function(ctx, contents, relativePath) { + var key = this.cacheKeyProcessString(contents, relativePath); + return this._peristentCache.get(key).then(function(entry) { + var result; + + if (entry.isCached) { + result = { + string: entry.value, + key: key + }; + } else { + result = { + string: ctx.processString(contents, relativePath), + key: key + }; + } + + return result; + }); + }, + + done: function(ctx, result) { + return this._peristentCache.set(result.key, result.string); + } +}; diff --git a/test/test.js b/test/test.js index e6785a7..d2104d0 100644 --- a/test/test.js +++ b/test/test.js @@ -308,7 +308,7 @@ describe('Filter', function() { }); it('cache is initialized', function() { - expect(f._peristentCache).to.be.ok; + expect(f.processor.processor._peristentCache).to.be.ok; }); it('default `baseDir` implementation throws an Unimplemented Exception', function() { @@ -320,7 +320,7 @@ describe('Filter', function() { }); it('`cacheKeyProcessString` return correct first level file cache', function() { - expect(f.cacheKeyProcessString('foo-bar-baz', 'relative-path')).to.eql('4c43793687f9a7170a9149ad391cbf70'); + expect(f.processor.processor.cacheKeyProcessString('foo-bar-baz', 'relative-path')).to.eql('4c43793687f9a7170a9149ad391cbf70'); }); it('filter properly reads file tree', function() { From 2ab33563045a542c4e55fe5a2e1f01d92500634b Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 12:01:42 -0700 Subject: [PATCH 4/7] Add cacheKey to constructor --- lib/strategies/persistent.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/strategies/persistent.js b/lib/strategies/persistent.js index 37fe74c..31447ee 100644 --- a/lib/strategies/persistent.js +++ b/lib/strategies/persistent.js @@ -12,7 +12,12 @@ module.exports = { if (/^win/.test(process.platform)) { console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); } - this._peristentCache = new PersistentCache(this.cacheKey(ctx), { + + if (!ctx.constructor.cacheKey) { + ctx.constructor.cacheKey = this.cacheKey(ctx); + } + + this._peristentCache = new PersistentCache(ctx.constructor.cacheKey, { compression: 'deflate' }); }, From 6fec4a45573b43a172e78de1b72ca6aae9d02e62 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 16:31:48 -0700 Subject: [PATCH 5/7] Revert equality checks --- index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 1a0c296..292ac92 100644 --- a/index.js +++ b/index.js @@ -108,12 +108,12 @@ Filter.prototype.canProcessFile = }; Filter.prototype.getDestFilePath = function getDestFilePath(relativePath) { - if (this.extensions === null) return relativePath; + if (this.extensions == null) return relativePath; for (var i = 0, ii = this.extensions.length; i < ii; ++i) { var ext = this.extensions[i]; if (relativePath.slice(-ext.length - 1) === '.' + ext) { - if (this.targetExtension !== null) { + if (this.targetExtension != null) { relativePath = relativePath.slice(0, -ext.length) + this.targetExtension; } @@ -188,9 +188,8 @@ Filter.prototype.processFile = var contents = fs.readFileSync( srcDir + '/' + relativePath, { encoding: inputEncoding }); - return this.processor.processString(this, contents, relativePath).then( - function asyncOutputFilteredFile(result) { - var outputString = result.string; + return this.processor.processString(this, contents, relativePath).then(function asyncOutputFilteredFile(result) { + var outputString = result.string; var outputPath = self.getDestFilePath(relativePath); if (outputPath == null) { throw new Error('canProcessFile("' + relativePath + '") is true, but getDestFilePath("' + relativePath + '") is null'); From 41b675177dd669060e5a0dffec454fd170471eb5 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 16:57:37 -0700 Subject: [PATCH 6/7] Expose the cacheKeyProcessString --- index.js | 12 +++++++++++- lib/strategies/persistent.js | 6 +----- test/test.js | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 292ac92..4e0e82d 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,6 @@ var Cache = require('./lib/cache'); var debugGenerator = require('debug'); var keyForFile = require('./lib/key-for-file'); var PersistentCache = require('async-disk-cache'); -var hashForDep = require('hash-for-dep'); var md5Hex = require('md5-hex'); var Processor = require('./lib/processor'); var defaultProccessor = require('./lib/strategies/default'); @@ -102,6 +101,17 @@ Filter.prototype.baseDir = function() { throw Error('Filter must implement prototype.baseDir'); }; +/** + * @public + * + * optionally override this to build a more rhobust cache key + * @param {String} string The contents of a file that is being processed + * @return {String} A cache key + */ +Filter.prototype.cacheKeyProcessString = function(string /*, relativePath*/) { + return md5Hex(string); +}; + Filter.prototype.canProcessFile = function canProcessFile(relativePath) { return !!this.getDestFilePath(relativePath); diff --git a/lib/strategies/persistent.js b/lib/strategies/persistent.js index 31447ee..9423046 100644 --- a/lib/strategies/persistent.js +++ b/lib/strategies/persistent.js @@ -26,12 +26,8 @@ module.exports = { return hashForDep(ctx.baseDir()); }, - cacheKeyProcessString: function(string) { - return md5Hex(string); - }, - processString: function(ctx, contents, relativePath) { - var key = this.cacheKeyProcessString(contents, relativePath); + var key = ctx.cacheKeyProcessString(contents, relativePath); return this._peristentCache.get(key).then(function(entry) { var result; diff --git a/test/test.js b/test/test.js index d2104d0..ac8df74 100644 --- a/test/test.js +++ b/test/test.js @@ -320,7 +320,7 @@ describe('Filter', function() { }); it('`cacheKeyProcessString` return correct first level file cache', function() { - expect(f.processor.processor.cacheKeyProcessString('foo-bar-baz', 'relative-path')).to.eql('4c43793687f9a7170a9149ad391cbf70'); + expect(f.cacheKeyProcessString('foo-bar-baz', 'relative-path')).to.eql('4c43793687f9a7170a9149ad391cbf70'); }); it('filter properly reads file tree', function() { From 4df505328c7ff78fa5f4b37522944b47af388606 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 19 Aug 2015 18:49:51 -0700 Subject: [PATCH 7/7] Don't bleed details about support level Prior to this commit we bled details about the support level for persistent builds. This places those details into 1 place so that when support for windows is there we simply can remove the strategy code. --- index.js | 8 ++------ lib/processor.js | 8 +++++++- lib/strategies/persistent.js | 4 ---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 4e0e82d..9272032 100644 --- a/index.js +++ b/index.js @@ -38,7 +38,7 @@ function Filter(inputTree, options) { Plugin.call(this, [inputTree]); - this.processor = new Processor(); + this.processor = new Processor(options); this.processor.setStrategy(defaultProccessor); /* Destructuring assignment in node 0.12.2 would be really handy for this! */ @@ -52,11 +52,7 @@ function Filter(inputTree, options) { if (options.outputEncoding != null) this.outputEncoding = options.outputEncoding; if (options.persist) { - if (/^win/.test(process.platform)) { - console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); - } else { - this.processor.setStrategy(require('./lib/strategies/persistent')); - } + this.processor.setStrategy(require('./lib/strategies/persistent')); } } diff --git a/lib/processor.js b/lib/processor.js index 6207713..7a12792 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -1,8 +1,14 @@ -function Processor() { +function Processor(options) { + options = options || {}; this.processor = {}; + this.persistent = options.persist; } Processor.prototype.setStrategy = function(stringProcessor) { + if (this.persistent && /^win/.test(process.platform)) { + console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); + return; + } this.processor = stringProcessor; }; diff --git a/lib/strategies/persistent.js b/lib/strategies/persistent.js index 9423046..8b2f84f 100644 --- a/lib/strategies/persistent.js +++ b/lib/strategies/persistent.js @@ -9,10 +9,6 @@ module.exports = { _peristentCache: {}, init: function(ctx) { - if (/^win/.test(process.platform)) { - console.log('Unfortunately persistent cache is currently not available on windows based systems. Please see https://github.com/stefanpenner/hash-for-dep/issues/8.'); - } - if (!ctx.constructor.cacheKey) { ctx.constructor.cacheKey = this.cacheKey(ctx); }