Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

filestream-cache

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

filestream-cache - npm Package Compare versions

Comparing version 0.0.2 to 1.0.0

107

index.js

@@ -8,2 +8,3 @@ var fs = require('fs');

var mkdirp = require('mkdirp');
var twelveHoursInSeconds = 43200;

@@ -16,4 +17,7 @@ /**

*/
function StreamCache(rootDirectory) {
function StreamCache(rootDirectory, options) {
this.rootCacheDirectory = rootDirectory;
options = options || {};
this.defaultTtl = options.defaultTtl || twelveHoursInSeconds;
this.serveStale = options.serveStale || false;

@@ -33,2 +37,31 @@ // TODO: Where's best to handle errors here?

StreamCache.prototype.getMetaData = function(identifier) {
var cachedObjectPath = this._getCachedObjectPath(identifier);
var cache = this;
return this._getReadFileDescriptor(identifier).then(function(fd) {
return cache._getMetaDataUsingFileDescriptor(fd);
});
};
StreamCache.prototype._getMetaDataUsingFileDescriptor = function(fd) {
return new Promise(function(resolve, reject) {
fs.fstat(fd, function(err, stat) {
if (err) {
reject(err);
return;
}
var lastModified = (stat.mtime.getTime() / 1000)|0;
var timeNowInSeconds = ((Date.now() / 1000)|0);
resolve({
age: timeNowInSeconds - lastModified,
firstCreated: (stat.birthtime.getTime() / 1000)|0,
lastModified: lastModified
});
});
});
};
/**

@@ -52,6 +85,15 @@ * Get a Stream from the cache, if the stream doesn't exist, create it via the

cache._read(identifier, options).then(function(stream) {
if (stream) {
if (!stream) {
var newStream;
try {
newStream = createCallback();
} catch(err) {
passThroughStream.emit('error', err);
throw err;
}
cache.writeThrough(identifier, newStream).pipe(passThroughStream);
} else {
stream.pipe(passThroughStream);
} else {
cache.writeThrough(identifier, createCallback()).pipe(passThroughStream);
}

@@ -123,27 +165,48 @@ });

StreamCache.prototype._read = function(identifier, options) {
options = options || {};
var cachedObjectPath = this._getCachedObjectPath(identifier);
var cache = this;
var newerThan = options.newerThan || 0;
return this._getReadFileDescriptor(identifier).then(function(fd) {
return cache._isStale(fd).then(function(isStale) {
if (isStale) {
return false;
} else {
// First argument of fs.createReadStream is ignored
// because the 'fd' is present
return fs.createReadStream(false, { fd: fd, autoClose: true });
}
});
}).catch(function(e) {
return false;
});
};
StreamCache.prototype.isStale = function(identifier) {
var cache = this;
return this._getReadFileDescriptor(identifier).then(function(fd) {
return cache._isStale(fd);
});
};
StreamCache.prototype._isStale = function(fd) {
var defaultTtl = this.defaultTtl;
return this._getMetaDataUsingFileDescriptor(fd).then(function(metadata) {
return metadata.age > defaultTtl;
});
};
StreamCache.prototype._getReadFileDescriptor = function(identifier, options) {
var cachedObjectPath = this._getCachedObjectPath(identifier);
return new Promise(function(resolve, reject) {
fs.open(cachedObjectPath, 'r', function(e, fd) {
if (e) {
resolve(false);
} else {
fs.fstat(fd, function(e, stats) {
if (stats.mtime < newerThan) {
resolve(false);
} else {
// First argument of fs.createReadStream is ignored
// because the 'fd' is present
var readStream = fs.createReadStream(false, { fd: fd });
readStream.on('end', function() {
// Close fd
fs.close(fd);
});
resolve(readStream);
}
});
reject(e);
return;
}
resolve(fd);
});

@@ -150,0 +213,0 @@ });

@@ -17,4 +17,4 @@ {

},
"version": "0.0.2",
"version": "1.0.0",
"license": "MIT"
}

@@ -1,3 +0,2 @@

var StreamCache = require('../index');
var fs = require('fs');
var StreamCache = require('../index'); var fs = require('fs');
var assert = require('assert');

@@ -9,2 +8,13 @@ var helpers = require('./testhelper');

describe("#isStale(identifier)", function() {
it("should return true, if the cache object is stale", function(done) {
helpers.testIsStale(-1, true, done);
});
it("should return false, if the cache object is not stale", function(done) {
helpers.testIsStale(4000, false, done);
});
});
describe("#purge(callback)", function() {

@@ -62,2 +72,45 @@ it("should purge any objects from the cache where the Promise returned from the callback resolves as true", function(done) {

describe("#get(identifier, options, callback)", function() {
it("should, if the cached object's age is older than the default ttl, create a new stream and overwrite the cache", function(done) {
var streamContent = 'my test stream content';
var testBucket = 'get#test-create-stale';
var cacheKey = 'testkey';
var testDirectory = helpers.localTestDirectory(testBucket);
var streamCache = new StreamCache(testDirectory, { defaultTtl: -1 });
var streamCreateCount = 0;
var cachedStream = streamCache.get(cacheKey, {}, function() {
streamCreateCount++;
return helpers.createStream(streamContent + " - first create").end();
});
cachedStream.on('data', function() { /* do nothing */ });
cachedStream.on('error', function(e) { rmrf(testDirectory); done(e); });
cachedStream.on('end', function() { next(); });
function next() {
var content = streamContent + " - second create";
var freshStream = streamCache.get(cacheKey, {}, function() {
streamCreateCount++;
return helpers.createStream(content).end();
});
var bufferedContent = "";
freshStream.on('data', function(data) {
bufferedContent += data.toString();
});
freshStream.on('error', function(e) { rmrf(testDirectory); done(e); });
freshStream.on('end', function() {
rmrf(testDirectory);
assert.equal(streamCreateCount, 2);
assert.equal(bufferedContent, content);
done();
});
}
});
it("should, if the cache key does not exist, create a new stream using the callback and cache it", function(done) {

@@ -64,0 +117,0 @@ var streamContent = 'my test stream content';

@@ -8,2 +8,3 @@ 'use strict';

var StreamCache = require('../index');
var assert = require('assert');

@@ -63,2 +64,38 @@ function localTestDirectory(bucket) {

function testIsStale(defaultTtl, isExpectedStale, done) {
var streamContent = 'my test stream content';
var testBucket = "isStale#true";
var testDirectory = localTestDirectory(testBucket);
var cacheKey = 'cachekey';
var streamCache = new StreamCache(testDirectory, { defaultTtl: defaultTtl });
var cachedStream = streamCache.get(cacheKey, {}, function() {
return createStream(streamContent).end();
});
cachedStream.on('error', function(e) {
rmrf(testDirectory);
done(e);
});
var bufferedData = '';
cachedStream.on('data', function(data) {
bufferedData += data.toString();
});
cachedStream.on('end', function() {
streamCache.isStale(cacheKey).then(function(isStale) {
assert.equal(isExpectedStale, isStale);
rmrf(testDirectory);
done();
}).catch(function(e) {
rmrf(testDirectory);
done(e);
});
});
}
module.exports = {

@@ -68,3 +105,4 @@ localTestDirectory: localTestDirectory,

testPurgeFunction: testPurgeFunction,
testIsStale: testIsStale,
createStream: createStream
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc