memoize-fs
Advanced tools
Comparing version 0.0.1 to 0.0.2
52
index.js
@@ -36,20 +36,38 @@ 'use strict'; | ||
function getCacheFilePath(fn, args, opt) { | ||
/* jshint unused: vars */ | ||
var circRefColl = [], | ||
fnJson = JSON.stringify(args, function (name, value) { | ||
if (typeof value === 'function') { | ||
function serialize(val) { | ||
if (!val) { return String(val); } | ||
if (typeof val === 'object') { | ||
/* jshint unused: vars */ | ||
var circRefColl = []; | ||
return JSON.stringify(val, function (name, value) { | ||
if (typeof value === 'function') { | ||
return;// value; | ||
} | ||
if (typeof value === 'object' && value !== null) { | ||
if (circRefColl.indexOf(value) !== -1) { | ||
// circular reference found, discard key | ||
return; | ||
} | ||
// store value in collection | ||
circRefColl.push(value); | ||
} | ||
return value; | ||
} | ||
if (typeof value === 'object' && value !== null) { | ||
if (circRefColl.indexOf(value) !== -1) { | ||
// circular reference found, discard key | ||
return; | ||
} | ||
// store value in collection | ||
circRefColl.push(value); | ||
} | ||
return value; | ||
}), | ||
salt = opt.salt || '', | ||
hash = crypto.createHash('md5').update(String(fn), fnJson + salt).digest('hex'); | ||
}); | ||
} | ||
return String(val); | ||
} | ||
var salt = opt.salt || '', | ||
fnStr = String(fn), | ||
argsStr, | ||
hash; | ||
if (opt.serialize !== undefined) { | ||
argsStr = serialize(opt.serialize); | ||
} else { | ||
argsStr = serialize(args); | ||
} | ||
hash = crypto.createHash('md5').update(fnStr + argsStr + salt).digest('hex'); | ||
return path.join(options.cachePath, opt.cacheId, hash); | ||
@@ -56,0 +74,0 @@ } |
{ | ||
"name": "memoize-fs", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "memoize/cache in file system solution for Node.js", | ||
@@ -5,0 +5,0 @@ "author": { |
@@ -13,3 +13,3 @@ memoize-fs | ||
* Works with any type and length of function arguments – __no serialization is needed__ | ||
* Works with almost all kind and any length of function arguments – [__custom serialization is posible__](#serialize) | ||
* Support for [__promisified functions__](#memoizing-promisified-functions) | ||
@@ -27,3 +27,3 @@ * Cache [__can be invalidated manually__](#manual-cache-invalidation) | ||
```javascript | ||
var memoize = require('memoize-fs')({ cachePath: require('path').join(__dirname, '../../build/cache' }), | ||
var memoize = require('memoize-fs')({ cachePath: require('path').join(__dirname, '../../cache' }), | ||
fun = function (a, b) { return a + b; }; | ||
@@ -77,4 +77,78 @@ | ||
### Configuration | ||
### Options | ||
####TODO: continue with docs here | ||
When memoizing a function all below options can be applied in any combination. | ||
#### cacheId | ||
By default all cache files are saved into the __root cache__ which is the folder specified by the cachePath option: | ||
```javascript | ||
var memoize = require('memoize-fs')({ cachePath: require('path').join(__dirname, '../../cache' }); | ||
``` | ||
The cacheId option which you can specify during momoization of a function resolves to the name of a subfolder created inside the root cache folder. Cached function calls will be cached inside that folder: | ||
```javascript | ||
memoize.fn(fun, { cacheId: foobar}).then(... | ||
``` | ||
#### salt | ||
Functions may have references to variables outside their own scope. As a consequence two functions which look exactly the same (they have the same function signature and function body) can return different results even when executed with identical arguments. In order to avoid the same cache being used for two different functions you can use the salt option which mutates the hash key created for the memoized function which in turn defines the location of the cache file: | ||
```javascript | ||
memoize.fn(fun, { salt: 'foobar'}).then(... | ||
``` | ||
#### force | ||
The force option forces the re-execution of an already memoized function and the re-caching of its outcome: | ||
```javascript | ||
memoize.fn(fun, { force: true}).then(... | ||
``` | ||
#### serialize | ||
memoize-fs tries to serialize the arguments of the memoized function in order to create a hash which is used as the name of the cache file to be stored or retrieved. | ||
If you want memoize-fs to use a custom key instead of letting it serialize the arguments, you can pass the key in the serialize option to memoize: | ||
```javascript | ||
memoize.fn(fun, { serialize: 'foobar'}).then(... | ||
``` | ||
Alternatively you can pass another object to be serialized in place of the arguments of the memoized function: | ||
```javascript | ||
memoize.fn(fun, { serialize: { foo: 'bar'}}).then(... | ||
``` | ||
### Manual cache invalidation | ||
You can delete the root cache (all cache files inside the folder specified by the cachePath option): | ||
```javascript | ||
memoized.invalidate().then(... | ||
``` | ||
You can also pass the cacheId argument to the invalidate method. This way you only delete the cache inside the subfolder with given id. | ||
```javascript | ||
memoized.invalidate('foobar').then(... | ||
``` | ||
## Contributing | ||
Issues and Pull-requests welcome. | ||
## Change Log | ||
v0.0.2 - [serialize option](#serialize) | ||
v0.0.1 - Alpha | ||
### Tests [![Build Status](https://api.travis-ci.org/borisdiakur/memoize-fs.png?branch=master)](https://travis-ci.org/borisdiakur/memoize-fs) | ||
$ npm test | ||
@@ -453,2 +453,80 @@ 'use strict'; | ||
describe('custom serialization', function () { | ||
it('should cache the result of a memoized function on second execution with option serialize of type string', function (done) { | ||
var cachePath = path.join(__dirname, '../../build/cache'), | ||
memoize = memoizeFs({ cachePath: cachePath }), | ||
c = 3; | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: 'qux' }).then(function (memFn) { | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 6, 'expected result to strictly equal 6'); | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: 'qux' }).then(function (memFn) { | ||
c = 999; | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 6, 'expected result to strictly equal 6'); | ||
fs.readdir(path.join(cachePath, 'foobar'), function (err, files) { | ||
if (err) { | ||
done(err); | ||
} else { | ||
assert.strictEqual(files.length, 1, 'expected exactly one file in cache with id foobar'); | ||
done(); | ||
} | ||
}); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}); | ||
it('should cache the result of a memoized function on second execution with option serialize of type object', function (done) { | ||
var cachePath = path.join(__dirname, '../../build/cache'), | ||
memoize = memoizeFs({ cachePath: cachePath }), | ||
c = 3; | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: {qux: 321} }).then(function (memFn) { | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 6, 'expected result to strictly equal 6'); | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: {qux: 321} }).then(function (memFn) { | ||
c = 999; | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 6, 'expected result to strictly equal 6'); | ||
fs.readdir(path.join(cachePath, 'foobar'), function (err, files) { | ||
if (err) { | ||
done(err); | ||
} else { | ||
assert.strictEqual(files.length, 1, 'expected exactly one file in cache with id foobar'); | ||
done(); | ||
} | ||
}); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}); | ||
it('should cache the results of two equal memoized functions with different options serialize set', function (done) { | ||
var cachePath = path.join(__dirname, '../../build/cache'), | ||
memoize = memoizeFs({ cachePath: cachePath }), | ||
c = 3; | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: {qux: 321} }).then(function (memFn) { | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 6, 'expected result to strictly equal 6'); | ||
memoize.fn(function (a, b) { return a + b + c; }, { cacheId: 'foobar', serialize: {qux: 123} }).then(function (memFn) { | ||
c = 4; | ||
memFn(1, 2).then(function (result) { | ||
assert.strictEqual(result, 7, 'expected result to strictly equal 6'); | ||
fs.readdir(path.join(cachePath, 'foobar'), function (err, files) { | ||
if (err) { | ||
done(err); | ||
} else { | ||
assert.strictEqual(files.length, 2, 'expected exactly two files in cache with id foobar'); | ||
done(); | ||
} | ||
}); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}, done); | ||
}); | ||
}) | ||
describe('invalidate cache', function () { | ||
@@ -455,0 +533,0 @@ |
93226
25
736
152