Add better error message if context file gets corrupted

This commit is contained in:
Nick O'Leary 2020-10-06 15:42:52 +01:00
parent 5e63471983
commit af636870d4
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
2 changed files with 18 additions and 10 deletions

View File

@ -137,16 +137,15 @@ function stringify(value) {
return { json: result, circular: hasCircular }; return { json: result, circular: hasCircular };
} }
async function writeFileAtomic(storagePath, content) {
function writeFileAtomic(storagePath, content) {
// To protect against file corruption, write to a tmp file first and then // To protect against file corruption, write to a tmp file first and then
// rename to the destination file // rename to the destination file
let finalFile = storagePath + ".json"; let finalFile = storagePath + ".json";
let tmpFile = finalFile + "."+Date.now()+".tmp"; let tmpFile = finalFile + "."+Date.now()+".tmp";
return fs.outputFile(tmpFile, content, "utf8").then(function() { await fs.outputFile(tmpFile, content, "utf8");
return fs.rename(tmpFile,finalFile); return fs.rename(tmpFile,finalFile);
})
} }
function LocalFileSystem(config){ function LocalFileSystem(config){
this.config = config; this.config = config;
this.storageBaseDir = getBasePath(this.config); this.storageBaseDir = getBasePath(this.config);
@ -169,6 +168,7 @@ LocalFileSystem.prototype.open = function(){
if (this.cache) { if (this.cache) {
var scopes = []; var scopes = [];
var promises = []; var promises = [];
var contextFiles = [];
return listFiles(self.storageBaseDir).then(function(files) { return listFiles(self.storageBaseDir).then(function(files) {
files.forEach(function(file) { files.forEach(function(file) {
var parts = file.split(path.sep); var parts = file.split(path.sep);
@ -179,15 +179,22 @@ LocalFileSystem.prototype.open = function(){
} else { } else {
scopes.push(parts[1].substring(0,parts[1].length-5)+":"+parts[0]); scopes.push(parts[1].substring(0,parts[1].length-5)+":"+parts[0]);
} }
promises.push(loadFile(path.join(self.storageBaseDir,file))); let contextFile = path.join(self.storageBaseDir,file);
contextFiles.push(contextFile)
promises.push(loadFile(contextFile));
}) })
return Promise.all(promises); return Promise.all(promises);
}).then(function(res) { }).then(function(res) {
scopes.forEach(function(scope,i) { scopes.forEach(function(scope,i) {
var data = res[i]?JSON.parse(res[i]):{}; try {
Object.keys(data).forEach(function(key) { var data = res[i]?JSON.parse(res[i]):{};
self.cache.set(scope,key,data[key]); Object.keys(data).forEach(function(key) {
}) self.cache.set(scope,key,data[key]);
})
} catch(err) {
let error = new Error(log._("context.localfilesystem.invalid-json",{file: contextFiles[i]}))
throw error;
}
}); });
}).catch(function(err){ }).catch(function(err){
if(err.code == 'ENOENT') { if(err.code == 'ENOENT') {

View File

@ -176,6 +176,7 @@
"error-invalid-default-module": "Default context store unknown: '__storage__'", "error-invalid-default-module": "Default context store unknown: '__storage__'",
"unknown-store": "Unknown context store '__name__' specified. Using default store.", "unknown-store": "Unknown context store '__name__' specified. Using default store.",
"localfilesystem": { "localfilesystem": {
"invalid-json": "Invalid JSON in context file '__file__'",
"error-circular": "Context __scope__ contains a circular reference that cannot be persisted", "error-circular": "Context __scope__ contains a circular reference that cannot be persisted",
"error-write": "Error writing context: __message__" "error-write": "Error writing context: __message__"
} }