Add caching to localfilesystem context

This commit is contained in:
Nick O'Leary 2018-07-02 22:32:20 +01:00
parent 7423583508
commit 43d7c8d48c
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
3 changed files with 140 additions and 32 deletions

View File

@ -29,7 +29,6 @@ module.exports = {
var scope = req.params.scope;
var id = req.params.id;
var key = req.params[0];
var result = {};
var ctx;
if (scope === 'global') {
ctx = redNodes.getContext('global');
@ -43,19 +42,28 @@ module.exports = {
}
if (ctx) {
if (key) {
result = util.encodeObject({msg:ctx.get(key)});
ctx.get(key,function(err, v) {
console.log(key,v);
res.json(util.encodeObject({msg:v}));
});
return;
} else {
var keys = ctx.keys();
var i = 0;
var l = keys.length;
while(i < l) {
var k = keys[i];
result[k] = util.encodeObject({msg:ctx.get(k)});
i++;
}
ctx.keys(function(err, keys) {
var result = {};
var c = keys.length;
keys.forEach(function(key) {
ctx.get(key,function(err, v) {
result[key] = util.encodeObject({msg:v});
c--;
if (c === 0) {
res.json(result);
}
});
});
});
}
} else {
res.json({});
}
res.json(result);
}
}

View File

@ -14,10 +14,39 @@
* limitations under the License.
**/
/**
* Local file-system based context storage
*
* Configuration options:
* {
* base: "contexts", // the base directory to use
* // default: "contexts"
* dir: "/path/to/storage", // the directory to create the base directory in
* // default: settings.userDir
* cache: true // whether to cache contents in memory
* // default: true
* }
*
*
* $HOME/.node-red/contexts
* global
* global_context.json
* <id of Flow 1>
* flow_context.json
* <id of Node a>.json
* <id of Node b>.json
* <id of Flow 2>
* flow_context.json
* <id of Node x>.json
* <id of Node y>.json
*/
var fs = require('fs-extra');
var path = require("path");
var util = require("../../util");
var MemoryStore = require("./memory");
function getStoragePath(storageBaseDir, scope) {
if(scope.indexOf(":") === -1){
if(scope === "global"){
@ -76,10 +105,48 @@ function loadFile(storagePath){
function LocalFileSystem(config){
this.config = config;
this.storageBaseDir = getBasePath(this.config);
if (config.hasOwnProperty('cache')?config.cache:true) {
this.cache = MemoryStore({});
}
}
LocalFileSystem.prototype.open = function(){
return Promise.resolve();
var self = this;
if (this.cache) {
var scopes = [];
var promises = [];
var subdirs = [];
var subdirPromises = [];
return fs.readdir(self.storageBaseDir).then(function(dirs){
dirs.forEach(function(fn) {
var p = getStoragePath(self.storageBaseDir ,fn)+".json";
scopes.push(fn);
promises.push(loadFile(p));
subdirs.push(path.join(self.storageBaseDir,fn));
subdirPromises.push(fs.readdir(path.join(self.storageBaseDir,fn)));
})
return Promise.all(subdirPromises);
}).then(function(dirs) {
dirs.forEach(function(files,i) {
files.forEach(function(fn) {
if (fn !== 'flow.json' && fn !== 'global.json') {
scopes.push(fn.substring(0,fn.length-5)+":"+scopes[i]);
promises.push(loadFile(path.join(subdirs[i],fn)))
}
});
})
return Promise.all(promises);
}).then(function(res) {
scopes.forEach(function(scope,i) {
var data = res[i]?JSON.parse(res[i]):{};
Object.keys(data).forEach(function(key) {
self.cache.set(scope,key,data[key]);
})
});
})
} else {
return Promise.resolve();
}
}
LocalFileSystem.prototype.close = function(){
@ -87,6 +154,9 @@ LocalFileSystem.prototype.close = function(){
}
LocalFileSystem.prototype.get = function(scope, key, callback) {
if (this.cache) {
return this.cache.get(scope,key,callback);
}
if(typeof callback !== "function"){
throw new Error("Callback must be a function");
}
@ -102,7 +172,7 @@ LocalFileSystem.prototype.get = function(scope, key, callback) {
});
};
LocalFileSystem.prototype.set =function(scope, key, value, callback) {
LocalFileSystem.prototype._set = function(scope, key, value, callback) {
var storagePath = getStoragePath(this.storageBaseDir ,scope);
loadFile(storagePath + ".json").then(function(data){
var obj = data ? JSON.parse(data) : {}
@ -117,9 +187,23 @@ LocalFileSystem.prototype.set =function(scope, key, value, callback) {
callback(err);
}
});
}
LocalFileSystem.prototype.set = function(scope, key, value, callback) {
if (this.cache) {
this.cache.set(scope,key,value,callback);
this._set(scope,key,value, function(err) {
// TODO: log any errors
});
} else {
this._set(scope,key,value,callback);
}
};
LocalFileSystem.prototype.keys = function(scope, callback){
if (this.cache) {
return this.cache.keys(scope,callback);
}
if(typeof callback !== "function"){
throw new Error("Callback must be a function");
}
@ -136,29 +220,45 @@ LocalFileSystem.prototype.keys = function(scope, callback){
};
LocalFileSystem.prototype.delete = function(scope){
var storagePath = getStoragePath(this.storageBaseDir ,scope);
return fs.remove(storagePath + ".json");
var cachePromise;
if (this.cache) {
cachePromise = this.cache.delete(scope);
} else {
cachePromise = Promise.resolve();
}
var that = this;
return cachePromise.then(function() {
var storagePath = getStoragePath(that.storageBaseDir,scope);
return fs.remove(storagePath + ".json");
});
}
LocalFileSystem.prototype.clean = function(activeNodes){
var self = this;
return fs.readdir(self.storageBaseDir).then(function(dirs){
return Promise.all(dirs.reduce(function(result, item){
if(item !== "global" && activeNodes.indexOf(item) === -1){
result.push(fs.remove(path.join(self.storageBaseDir,item)));
var cachePromise;
if (this.cache) {
cachePromise = this.cache.clean(activeNodes);
} else {
cachePromise = Promise.resolve();
}
return cachePromise.then(function() {
return fs.readdir(self.storageBaseDir).then(function(dirs){
return Promise.all(dirs.reduce(function(result, item){
if(item !== "global" && activeNodes.indexOf(item) === -1){
result.push(fs.remove(path.join(self.storageBaseDir,item)));
}
return result;
},[]));
}).catch(function(err){
if(err.code == 'ENOENT') {
return Promise.resolve();
}else{
return Promise.reject(err);
}
return result;
},[]));
}).catch(function(err){
if(err.code == 'ENOENT') {
return Promise.resolve();
}else{
return Promise.reject(err);
}
});
});
}
module.exports = function(config){
return new LocalFileSystem(config);
};

View File

@ -29,7 +29,7 @@ describe('localfilesystem',function() {
});
beforeEach(function() {
context = LocalFileSystem({dir: resourcesDir});
context = LocalFileSystem({dir: resourcesDir, cache: false});
return context.open();
});
@ -308,7 +308,7 @@ describe('localfilesystem',function() {
done();
});
});
});
}).catch(done);
});
});
});
@ -375,4 +375,4 @@ describe('localfilesystem',function() {
});
});
});
});
});