Skip to content

Commit

Permalink
Formatting and promise chain function naming
Browse files Browse the repository at this point in the history
  • Loading branch information
Munter committed Jul 25, 2016
1 parent 762671e commit cc9013b
Showing 1 changed file with 97 additions and 62 deletions.
159 changes: 97 additions & 62 deletions lib/Skrin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ Skrin.prototype = {
if (this._statCache[path]) {
return Promise.resolve(this._statCache[path]);
} else {
return fs.statAsync(path).tap(function (stats) {
that._statCache[path] = stats;
});
return fs.statAsync(path)
.tap(function saveToStatCache(stats) {
that._statCache[path] = stats;
});
}
},

Expand All @@ -62,6 +63,7 @@ Skrin.prototype = {

_deserializeCacheRecord: function (buffer) {
var cacheRecord = {};

for (var i = 0 ; i < buffer.length ; i += 1) {
if (buffer[i] === 0x0a) {
cacheRecord.metadata = JSON.parse(buffer.slice(0, i).toString('utf-8'));
Expand All @@ -77,23 +79,29 @@ Skrin.prototype = {
_writeCacheRecordToDisc: function (key, cacheRecord) {
var that = this;
debug('_writeCacheRecordToDisc %s', key);

var metadata = _.extend({}, cacheRecord); // Shallow copy
metadata.payloads = {};
var serializedPayloads = [];
var offset = 0;

Object.keys(cacheRecord.payloads).forEach(function (payloadName) {
var payload = cacheRecord.payloads[payloadName];
var serializedPayload = Buffer.isBuffer(payload) ? payload : new Buffer(payload, 'utf-8');
metadata.payloads[payloadName] = {name: payloadName, start: offset, end: offset + serializedPayload.length};
offset += serializedPayload.length;
serializedPayloads.push(serializedPayload);
});

var tempFileName = pathModule.resolve(that.cacheDir, uuid());

return fs.openAsync(tempFileName, 'ax')
.caught(function (err) {
.caught(function handleMissingCacheDir(err) {
debug('_writeCacheRecordToDisc - error opening %s for writing: %s', tempFileName, err.code);

if (err.code === 'ENOENT') {
debug('_writeCacheRecordToDisc - creating cache dir');

return mkdirpAsync(that.cacheDir)
.then(function () {
return fs.openAsync(tempFileName, 'ax');
Expand All @@ -102,19 +110,19 @@ Skrin.prototype = {
throw err;
}
})
.tap(function (fd) {
.tap(function writeMetadataToFile(fd) {
var jsonBuffer = new Buffer(JSON.stringify(metadata) + '\n');
return fs.writeAsync(fd, new Buffer(jsonBuffer, 'utf-8'), 0, jsonBuffer.length, null);
})
.tap(function (fd) {
.tap(function writePayloadsToFile(fd) {
return Promise.each(serializedPayloads, function (serializedPayload) {
return fs.writeAsync(fd, serializedPayload, 0, serializedPayload.length, null);
});
})
.then(function (fd) {
.then(function closeFile(fd) {
return fs.closeAsync(fd);
})
.then(function () {
.then(function moveTempFileToTarget() {
debug('_writeCacheRecordToDisc - successfully wrote %s', tempFileName);
return fs.renameAsync(tempFileName, pathModule.resolve(that.cacheDir, that._keyToCachedFileName(key)));
})
Expand All @@ -126,97 +134,124 @@ Skrin.prototype = {
_assertCacheRecordFreshness: function (cacheRecord) {
debug('_assertCacheRecordFreshness %s', cacheRecord.metadata.key);
var that = this;

return Promise.all(cacheRecord.metadata.sourcePaths.map(function (sourcePath) {
debug('_assertCacheRecordFreshness - checking source path %s', sourcePath);
return that.statAsync(sourcePath)
.caught(function (err) {
debug('_assertCacheRecordFreshness - %s stat resulted in error %s', sourcePath, err.code);
throw err;
})
.then(function (stats) {
debug('_assertCacheRecordFreshness - comparing %d to %d', stats.mtime.getTime(), cacheRecord.metadata.minimumMtime);
if (stats.mtime.getTime() >= cacheRecord.metadata.minimumMtime) {
debug('_assertCacheRecordFreshness - source path %s not fresh', sourcePath);
throw new Error('not fresh');
}
}, function (err) {
debug('_assertCacheRecordFreshness - %s stat resulted in error %s', sourcePath, err.code);
throw err;
}).tap(function () {
})
.tap(function () {
debug('_assertCacheRecordFreshness - cache hit for %s', cacheRecord.metadata.key);
});
})).then(function () {
}))
.then(function () {
return cacheRecord;
});
},

read: function (key) {
debug('read %s', key);
var that = this;

if (!that.mutexByKey[key]) {
debug('read - locking %s', key);
that.mutexByKey[key] = Promise.resolve().then(function () {
var cacheRecord = that.memoryCache[key];
if (cacheRecord) {
debug('read - found memory cache record for %s', key);
return that._assertCacheRecordFreshness(cacheRecord).caught(function () {

that.mutexByKey[key] = Promise.resolve()
.then(function getCacheRecord() {
var cacheRecord = that.memoryCache[key];

if (cacheRecord) {
debug('read - found memory cache record for %s', key);

return that._assertCacheRecordFreshness(cacheRecord)
.caught(function () {
return that._tryLoadCacheRecordFromDisc(key);
});
} else {
return that._tryLoadCacheRecordFromDisc(key);
});
} else {
return that._tryLoadCacheRecordFromDisc(key);
}
})
.tap(function (cacheRecord) {
that.memoryCache[key] = cacheRecord;
})
.finally(function () {
debug('read - unlocking %s', key);
that.mutexByKey[key] = null;
});
}
})
.tap(function storeRecordInMemory(cacheRecord) {
that.memoryCache[key] = cacheRecord;
})
.finally(function unlock() {
debug('read - unlocking %s', key);

that.mutexByKey[key] = null;
});
} else {
debug('read - waiting for lock %s', key);
}

return that.mutexByKey[key];
},

_tryLoadCacheRecordFromDisc: function (key) {
var that = this;
debug('_tryLoadCacheRecordFromDisc %s', key);
return fs.readFileAsync(this._keyToCachedFileName(key)).then(function (buffer) {
var cacheRecord = that._deserializeCacheRecord(buffer);
return that._assertCacheRecordFreshness(cacheRecord).caught(function () {
return that._populateAndAddToCache(key);

return fs.readFileAsync(this._keyToCachedFileName(key))
.then(function (buffer) {
var cacheRecord = that._deserializeCacheRecord(buffer);

return that._assertCacheRecordFreshness(cacheRecord)
.caught(function handleStaleCacheRecord() {
return that._populateAndAddToCache(key);
});
})
.caught(function handleMissingDiskCache(err) {
if (err.code === 'ENOENT') {
debug('_tryLoadCacheRecordFromDisc - %s ENOENT, proceeding to build it', key);
return that._populateAndAddToCache(key);
} else {
debug('_tryLoadCacheRecordFromDisc - %s %s', key, err.code);
throw err;
}
});
}, function (err) {
if (err.code === 'ENOENT') {
debug('_tryLoadCacheRecordFromDisc - %s ENOENT, proceeding to build it', key);
return that._populateAndAddToCache(key);
} else {
debug('_tryLoadCacheRecordFromDisc - %s %s', key, err.code);
throw err;
}
});
},

_populateAndAddToCache: function (key) {
var that = this;
debug('_populateAndAddToCache %s', key);

var startTime = Date.now();
return this.populate(key).then(function (cacheRecord) {
// Subtract 1000ms from minimumMtime.
// Due to low mtime resolution (s rather than ms) a file modification within the same whole second will appear
// as having happened before the startTime, which is incorrect. Therefore we don't trust the mtime unless
// the difference is at least 1000ms
cacheRecord.metadata.minimumMtime = startTime - 1000;
cacheRecord.metadata.key = key;
return cacheRecord;
}).tap(function (cacheRecord) {
that.watcher.add(cacheRecord.metadata.sourcePaths);
if (that.persist) {
debug('_populateAndAddToCache - checking if we want to persist it %s', key);
return that._assertCacheRecordFreshness(cacheRecord).then(function () {
return that._writeCacheRecordToDisc(key, cacheRecord);
}, function (err) {
// The cache record is no longer fresh. Just don't write it to disc.
});
}
});

return this.populate(key)
.then(function modifyCacheRecordMetadata(cacheRecord) {
// Subtract 1000ms from minimumMtime.
// Due to low mtime resolution (s rather than ms) a file modification within the same whole second will appear
// as having happened before the startTime, which is incorrect. Therefore we don't trust the mtime unless
// the difference is at least 1000ms
cacheRecord.metadata.minimumMtime = startTime - 1000;
cacheRecord.metadata.key = key;

return cacheRecord;
})
.tap(function addFileWatchers(cacheRecord) {
that.watcher.add(cacheRecord.metadata.sourcePaths);
})
.tap(function persistCacheRecordToDisc(cacheRecord) {
if (that.persist) {
debug('_populateAndAddToCache - checking if we want to persist it %s', key, cacheRecord);

return that._assertCacheRecordFreshness(cacheRecord)
.then(function () {
return that._writeCacheRecordToDisc(key, cacheRecord);
})
.caught(function noop(err) {
// The cache record is no longer fresh. Just don't write it to disc.
});
}
});
}
};

Expand Down

0 comments on commit cc9013b

Please sign in to comment.