Allow multiple instances of a given storage module to exist

This commit is contained in:
HirokiUchikawa 2018-05-24 21:42:40 +09:00
parent 7fafa21a1b
commit 28d05e2449
6 changed files with 157 additions and 144 deletions

View File

@ -29,8 +29,8 @@ function init(_settings) {
externalContexts = {}; externalContexts = {};
// init memory plugin // init memory plugin
externalContexts["_"] = require("./memory"); var memory = require("./memory");
externalContexts["_"].init(); externalContexts["_"] = memory();
globalContext = createContext("global",settings.functionGlobalContext || {}); globalContext = createContext("global",settings.functionGlobalContext || {});
} }
@ -61,8 +61,7 @@ function load() {
} else { } else {
plugin = plugins[pluginName].module; plugin = plugins[pluginName].module;
} }
plugin.init(config); externalContexts[pluginName] = plugin(config);
externalContexts[pluginName] = plugin;
}else{ }else{
throw new Error(log._("context.error-module-not-defined", {storage:pluginName})); throw new Error(log._("context.error-module-not-defined", {storage:pluginName}));
} }

View File

@ -18,61 +18,64 @@ var JsonDB = require('node-json-db');
var fs = require('fs-extra'); var fs = require('fs-extra');
var path = require("path"); var path = require("path");
var configs; function createStorage(storageBaseDir, scope) {
var storageBaseDir;
var storages;
function createStorage(scope) {
var i = scope.indexOf(":") var i = scope.indexOf(":")
if(i === -1){ if(i === -1){
if(scope === "global"){ if(scope === "global"){
storages[scope] = new JsonDB(path.join(storageBaseDir,"global",scope), true, true); return new JsonDB(path.join(storageBaseDir,"global",scope), true, true);
}else{ // scope:flow }else{ // scope:flow
storages[scope] = new JsonDB(path.join(storageBaseDir,scope,"flow"), true, true); return new JsonDB(path.join(storageBaseDir,scope,"flow"), true, true);
} }
}else{ // scope:local }else{ // scope:local
var ids = scope.split(":") var ids = scope.split(":")
storages[scope] = new JsonDB(path.join(storageBaseDir,ids[1],ids[0]), true, true); return new JsonDB(path.join(storageBaseDir,ids[1],ids[0]), true, true);
} }
} }
var localfilesystem = { function getStoragePath(config) {
init: function(_configs) { var base = config.base || "contexts";
configs = _configs; var storageBaseDir;
storages = {}; if (!config.dir) {
if (!configs.dir) { if(config.settings && config.settings.userDir){
if(configs.settings && configs.settings.userDir){ storageBaseDir = path.join(config.settings.userDir, base);
storageBaseDir = path.join(configs.settings.userDir,"contexts");
}else{ }else{
try { try {
fs.statSync(path.join(process.env.NODE_RED_HOME,".config.json")); fs.statSync(path.join(process.env.NODE_RED_HOME,".config.json"));
storageBaseDir = path.join(process.env.NODE_RED_HOME,"contexts"); storageBaseDir = path.join(process.env.NODE_RED_HOME, base);
} catch(err) { } catch(err) {
try { try {
// Consider compatibility for older versions // Consider compatibility for older versions
if (process.env.HOMEPATH) { if (process.env.HOMEPATH) {
fs.statSync(path.join(process.env.HOMEPATH,".node-red",".config.json")); fs.statSync(path.join(process.env.HOMEPATH,".node-red",".config.json"));
storageBaseDir = path.join(process.env.HOMEPATH,".node-red","contexts"); storageBaseDir = path.join(process.env.HOMEPATH, ".node-red", base);
} }
} catch(err) { } catch(err) {
} }
if (!storageBaseDir) { if (!storageBaseDir) {
storageBaseDir = path.join(process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH || process.env.NODE_RED_HOME,".node-red","contexts"); storageBaseDir = path.join(process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH || process.env.NODE_RED_HOME,".node-red", base);
} }
} }
} }
}else{ }else{
storageBaseDir = configs.dir; storageBaseDir = path.join(config.dir, base);
} }
}, return storageBaseDir;
get: function (scope, key) { }
if(!storages[scope]){
createStorage(scope); function LocalFileSystem(config){
this.config = config;
this.storageBaseDir = getStoragePath(this.config);
this.storages = {};
}
LocalFileSystem.prototype.get = function (scope, key) {
if(!this.storages[scope]){
return undefined;
} }
try{ try{
storages[scope].reload(); this.storages[scope].reload();
return storages[scope].getData("/" + key.replace(/\./g,"/")); return this.storages[scope].getData("/" + key.replace(/\./g,"/"));
}catch(err){ }catch(err){
if(err.name === "DataError"){ if(err.name === "DataError"){
return undefined; return undefined;
@ -80,40 +83,44 @@ var localfilesystem = {
throw err; throw err;
} }
} }
}, }
set: function (scope, key, value) { LocalFileSystem.prototype.set = function(scope, key, value) {
if(!storages[scope]){ if(!this.storages[scope]){
createStorage(scope); this.storages[scope] = createStorage(this.storageBaseDir ,scope);
} }
if(value){ if(value){
storages[scope].push("/" + key.replace(/\./g,"/"), value); this.storages[scope].push("/" + key.replace(/\./g,"/"), value);
}else{ }else{
storages[scope].delete("/" + key.replace(/\./g,"/")); this.storages[scope].delete("/" + key.replace(/\./g,"/"));
} }
}, }
keys: function (scope) {
if(!storages[scope]){ LocalFileSystem.prototype.keys = function(scope) {
if(!this.storages[scope]){
return []; return [];
} }
return Object.keys(storages[scope].getData("/")); return Object.keys(this.storages[scope].getData("/"));
}, }
delete: function(scope){
if(storages[scope]){ LocalFileSystem.prototype.delete = function(scope){
storages[scope].delete("/"); if(this.storages[scope]){
this.storages[scope].delete("/");
if(scope.indexOf(":") === -1){ if(scope.indexOf(":") === -1){
fs.removeSync(path.dirname(storages[scope].filename)); fs.removeSync(path.dirname(this.storages[scope].filename));
}else{ }else{
try{ try{
fs.statSync(storages[scope].filename); fs.statSync(this.storages[scope].filename);
fs.unlinkSync(storages[scope].filename); fs.unlinkSync(this.storages[scope].filename);
}catch(err){ }catch(err){
console.log("deleted"); console.log("deleted");
} }
} }
delete storages[scope]; delete this.storages[scope];
}
} }
}
module.exports = function(config){
return new LocalFileSystem(config);
}; };
module.exports = localfilesystem;

View File

@ -16,43 +16,53 @@
var util = require("../../util"); var util = require("../../util");
var data; function Memory(config){
this.data = {};
}
var memory = { Memory.prototype.get = function(scope, key) {
init: function(config) { if(!this.data[scope]){
data = {}; return undefined;
},
get: function(scope, key) {
if(!data[scope]){
data[scope] = {};
} }
return util.getMessageProperty(data[scope],key); return util.getMessageProperty(this.data[scope],key);
}, };
set: function(scope, key, value) {
if(!data[scope]){ Memory.prototype.set =function(scope, key, value) {
data[scope] = {}; if(!this.data[scope]){
this.data[scope] = {};
} }
util.setMessageProperty(data[scope],key,value); util.setMessageProperty(this.data[scope],key,value);
}, };
keys: function(scope){
if(!data[scope]){ Memory.prototype.keys = function(scope){
data[scope] = {}; if(!this.data[scope]){
return [];
} }
var keysData = Object.keys(data[scope]);
if (scope !== "global") { if (scope !== "global") {
return keysData; return Object.keys(this.data[scope]);
} else { } else {
return keysData.filter(function (key) { return Object.keys(this.data[scope]).filter(function (key) {
return key !== "set" && key !== "get" && key !== "keys"; return key !== "set" && key !== "get" && key !== "keys";
}); });
} }
},
delete: function(scope){
delete data[scope];
},
setGlobalContext: function(seed){
data["global"] = seed;
}
}; };
module.exports = memory; Memory.prototype.delete = function(scope){
delete this.data[scope];
};
Memory.prototype.open = function(){
return true;
};
Memory.prototype.close = function(){
delete this.data;
};
Memory.prototype.setGlobalContext= function(seed){
this.data["global"] = seed;
};
module.exports = function(config){
return new Memory(config);
};

View File

@ -151,14 +151,13 @@ describe('context', function() {
var stubDelete = sinon.stub(); var stubDelete = sinon.stub();
var contextStorage={ var contextStorage={
test:{ test:{
module: { module: function(config){
init: function() { function Test(){}
return true; Test.prototype.get = stubGet;
}, Test.prototype.set = stubSet;
get: stubGet, Test.prototype.keys = stubKeys;
set: stubSet, Test.prototype.delete = stubDelete;
keys: stubKeys, return new Test(config);
delete: stubDelete
}, },
config:{} config:{}
} }
@ -228,14 +227,13 @@ describe('context', function() {
var contextDefaultStorage={ var contextDefaultStorage={
default: "test", default: "test",
test:{ test:{
module: { module: function(config){
init: function() { function Test(){}
return true; Test.prototype.get = stubGet;
}, Test.prototype.set = stubSet;
get: stubGet, Test.prototype.keys = stubKeys;
set: stubSet, Test.prototype.delete = stubDelete;
keys: stubKeys, return new Test(config);
delete: stubDelete
}, },
config:{} config:{}
} }

View File

@ -17,23 +17,21 @@
var should = require('should'); var should = require('should');
var fs = require('fs-extra'); var fs = require('fs-extra');
var path = require("path"); var path = require("path");
var context = require('../../../../../red/runtime/nodes/context/localfilesystem'); var LocalFileSystem = require('../../../../../red/runtime/nodes/context/localfilesystem');
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context")); var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
describe('localfilesystem',function() { describe('localfilesystem',function() {
var context;
beforeEach(function() { beforeEach(function() {
context.init({dir: resourcesDir}); context = LocalFileSystem({dir: resourcesDir});
}); });
afterEach(function() { afterEach(function(done) {
context.delete("nodeX"); fs.remove(resourcesDir).then(function(result){
context.delete("nodeY"); return done(result);
}); });
after(function() {
fs.removeSync(resourcesDir);
}); });
describe('#get/set',function() { describe('#get/set',function() {

View File

@ -15,12 +15,13 @@
**/ **/
var should = require('should'); var should = require('should');
var context = require('../../../../../red/runtime/nodes/context/memory'); var Memory = require('../../../../../red/runtime/nodes/context/memory');
describe('memory',function() { describe('memory',function() {
var context;
beforeEach(function() { beforeEach(function() {
context.init({}); context = Memory({});
}); });
describe('#get/set',function() { describe('#get/set',function() {