Fix race condition on saving config

This commit is contained in:
Nick O'Leary 2014-09-23 17:09:23 +01:00
parent 6305c5b55f
commit 9152daa13b
5 changed files with 54 additions and 18 deletions

View File

@ -118,6 +118,7 @@ module.exports = {
getNodeConfigs: registry.getNodeConfigs, getNodeConfigs: registry.getNodeConfigs,
getNodeConfig: registry.getNodeConfig, getNodeConfig: registry.getNodeConfig,
clearRegistry: registry.clear, clearRegistry: registry.clear,
cleanNodeList: registry.cleanNodeList,
// Flow handling // Flow handling
loadFlows: flows.load, loadFlows: flows.load,

View File

@ -69,7 +69,11 @@ var registry = (function() {
nodeList[i] = n; nodeList[i] = n;
} }
} }
settings.set("nodes",nodeList); if (settings.available()) {
return settings.set("nodes",nodeList);
} else {
return when.reject("Settings unavailable");
}
} }
return { return {
@ -271,7 +275,22 @@ var registry = (function() {
return filterNodeInfo(config); return filterNodeInfo(config);
}, },
saveNodeList: saveNodeList saveNodeList: saveNodeList,
cleanNodeList: function() {
var removed = false;
for (var id in nodeConfigs) {
if (nodeConfigs.hasOwnProperty(id)) {
if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) {
registry.removeNode(id);
removed = true;
}
}
}
if (removed) {
saveNodeList();
}
}
} }
})(); })();
@ -547,10 +566,12 @@ function load(defaultNodesDir,disableNodePathScan) {
when.settle(promises).then(function(results) { when.settle(promises).then(function(results) {
// Trigger a load of the configs to get it precached // Trigger a load of the configs to get it precached
registry.getAllNodeConfigs(); registry.getAllNodeConfigs();
if (settings.available()) { if (settings.available()) {
registry.saveNodeList(); resolve(registry.saveNodeList());
} else {
resolve();
} }
resolve();
}); });
}); });
} }
@ -608,11 +629,12 @@ function loadNodeList(nodes) {
}); });
return when.settle(promises).then(function(results) { return when.settle(promises).then(function(results) {
registry.saveNodeList(); return registry.saveNodeList().then(function() {
var list = results.map(function(r) { var list = results.map(function(r) {
return filterNodeInfo(r.value); return filterNodeInfo(r.value);
});
return list;
}); });
return list;
}); });
} }
@ -666,5 +688,6 @@ module.exports = {
disableNode: registry.disableNodeSet, disableNode: registry.disableNodeSet,
addModule: addModule, addModule: addModule,
removeModule: registry.removeModule removeModule: registry.removeModule,
cleanNodeList: registry.cleanNodeList
} }

View File

@ -330,13 +330,19 @@ function start() {
var promises = []; var promises = [];
for (i in missingModules) { for (i in missingModules) {
if (missingModules.hasOwnProperty(i)) { if (missingModules.hasOwnProperty(i)) {
util.log(" - "+i+": "+missingModules[i].join(", ")); util.log("[red] - "+i+": "+missingModules[i].join(", "));
installModule(i).otherwise(function(err) { if (settings.autoInstallModules) {
// Error already reported. Need the otherwise handler installModule(i).otherwise(function(err) {
// to stop the error propagating any further // Error already reported. Need the otherwise handler
}); // to stop the error propagating any further
});
}
} }
} }
if (!settings.autoInstallModules) {
util.log("[red] Removing modules from config");
redNodes.cleanNodeList();
}
} }
defer.resolve(); defer.resolve();

View File

@ -216,7 +216,12 @@ var localfilesystem = {
if (fs.existsSync(globalSettingsFile)) { if (fs.existsSync(globalSettingsFile)) {
return nodeFn.call(fs.readFile,globalSettingsFile,'utf8').then(function(data) { return nodeFn.call(fs.readFile,globalSettingsFile,'utf8').then(function(data) {
if (data) { if (data) {
return JSON.parse(data); try {
return JSON.parse(data);
} catch(err) {
util.log("[red] Corrupted config detected - resetting");
return {};
}
} else { } else {
return {}; return {};
} }

View File

@ -17,6 +17,7 @@
var should = require("should"); var should = require("should");
var sinon = require("sinon"); var sinon = require("sinon");
var path = require("path"); var path = require("path");
var when = require("when");
var RedNodes = require("../../../red/nodes"); var RedNodes = require("../../../red/nodes");
var RedNode = require("../../../red/nodes/Node"); var RedNode = require("../../../red/nodes/Node");
@ -33,7 +34,7 @@ describe('NodeRegistry', function() {
function stubSettings(s,available) { function stubSettings(s,available) {
s.available = function() {return available;} s.available = function() {return available;}
s.set = function(s,v) {}, s.set = function(s,v) { return when.resolve()},
s.get = function(s) { return null;} s.get = function(s) { return null;}
return s return s
} }
@ -294,7 +295,7 @@ describe('NodeRegistry', function() {
var settings = { var settings = {
nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2",resourcesDir + "TestNode3"], nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2",resourcesDir + "TestNode3"],
available: function() { return true; }, available: function() { return true; },
set: function(s,v) {}, set: function(s,v) {return when.resolve();},
get: function(s) { return null;} get: function(s) { return null;}
} }
var settingsSave = sinon.spy(settings,"set"); var settingsSave = sinon.spy(settings,"set");
@ -327,7 +328,7 @@ describe('NodeRegistry', function() {
it('allows nodes to be added by filename', function(done) { it('allows nodes to be added by filename', function(done) {
var settings = { var settings = {
available: function() { return true; }, available: function() { return true; },
set: function(s,v) {}, set: function(s,v) {return when.resolve();},
get: function(s) { return null;} get: function(s) { return null;}
} }
typeRegistry.init(settings); typeRegistry.init(settings);