1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Prevent race condition (#1889)

* Make pending Flag to be deleted after write process complete.

* Prevent executing write process until the previous process is completed

* Fix to prevent file write race condition when closing file context

* Make flushing rerun if pendingWrites was added
This commit is contained in:
Hiroki Uchikawa 2018-09-17 05:15:23 +09:00 committed by Nick O'Leary
parent a8ec032553
commit fd86035865

View File

@ -142,6 +142,7 @@ function LocalFileSystem(config){
this.storageBaseDir = getBasePath(this.config);
if (config.hasOwnProperty('cache')?config.cache:true) {
this.cache = MemoryStore({});
this.writePromise = Promise.resolve();
}
this.pendingWrites = {};
this.knownCircularRefs = {};
@ -203,8 +204,22 @@ LocalFileSystem.prototype.open = function(){
log.debug("Flushing localfilesystem context scope "+scope);
promises.push(fs.outputFile(storagePath + ".json", stringifiedContext.json, "utf8"));
});
return Promise.all(promises).then(function(){
if(Object.keys(self.pendingWrites).length > 0){
// Rerun flushing if pendingWrites was added when the promise was running
return new Promise(function(resolve, reject) {
setTimeout(function() {
self._flushPendingWrites.call(self).then(function(){
resolve();
}).catch(function(err) {
reject(err);
});
}, self.flushInterval);
});
} else {
delete self._pendingWriteTimeout;
return Promise.all(promises);
}
});
}
});
} else {
@ -213,10 +228,16 @@ LocalFileSystem.prototype.open = function(){
}
LocalFileSystem.prototype.close = function(){
if (this.cache && this._flushPendingWrites) {
var self = this;
if (this.cache && this._pendingWriteTimeout) {
clearTimeout(this._pendingWriteTimeout);
delete this._pendingWriteTimeout;
return this._flushPendingWrites();
this.flushInterval = 0;
return this.writePromise.then(function(){
if(Object.keys(self.pendingWrites).length > 0) {
return self._flushPendingWrites();
}
});
}
return Promise.resolve();
}
@ -277,8 +298,10 @@ LocalFileSystem.prototype.set = function(scope, key, value, callback) {
return;
} else {
this._pendingWriteTimeout = setTimeout(function() {
self._flushPendingWrites.call(self).catch(function(err) {
log.error(log._("context.localfilesystem.error-write",{message:err.toString()}))
self.writePromise = self.writePromise.then(function(){
return self._flushPendingWrites.call(self).catch(function(err) {
log.error(log._("context.localfilesystem.error-write",{message:err.toString()}));
});
});
}, this.flushInterval);
}