Use safe file writing pattern (#421)

Write new file contents to a temporary file and then rename over the
target file to avoid data loss in the unlikely event there's an error
writing the new file contents or the process is interrupted.

Resolves #416.
This commit is contained in:
Hornwitser authored and GitHub committed 2021-11-03 16:14:18 +01:00
1 parent 9e7a7a602f
commit e23d07e965
15 files changed
+94 -35

No files matched your search

+2 -1
View File
@@ -2,6 +2,7 @@
const fs = require("fs-extra");
const path = require("path");
const libFileOps = require("@clusterio/lib/file_ops");
const libPlugin = require("@clusterio/lib/plugin");
const libErrors = require("@clusterio/lib/errors");
@@ -26,7 +27,7 @@ async function saveDatabase(masterConfig, playerDatastore, logger) {
let file = path.resolve(masterConfig.get("master.database_directory"), "inventories.json");
logger.verbose(`writing ${file}`);
let content = JSON.stringify(Array.from(playerDatastore));
await fs.outputFile(file, content);
await libFileOps.safeOutputFile(file, content);
}
}
+2 -1
View File
@@ -2,6 +2,7 @@
const fs = require("fs-extra");
const path = require("path");
const libFileOps = require("@clusterio/lib/file_ops");
const libPlugin = require("@clusterio/lib/plugin");
const RateLimiter = require("@clusterio/lib/RateLimiter");
@@ -25,7 +26,7 @@ async function loadTechnologies(masterConfig, logger) {
async function saveTechnologies(masterConfig, technologies, logger) {
let filePath = path.join(masterConfig.get("master.database_directory"), "technologies.json");
logger.verbose(`writing ${filePath}`);
await fs.outputFile(filePath, JSON.stringify([...technologies.entries()], null, 4));
await libFileOps.safeOutputFile(filePath, JSON.stringify([...technologies.entries()], null, 4));
}
class MasterPlugin extends libPlugin.BaseMasterPlugin {
+2 -1
View File
@@ -3,6 +3,7 @@ const fs = require("fs-extra");
const path = require("path");
const libDatabase = require("@clusterio/lib/database");
const libFileOps = require("@clusterio/lib/file_ops");
const libPlugin = require("@clusterio/lib/plugin");
const { Counter, Gauge } = require("@clusterio/lib/prometheus");
const RateLimiter = require("@clusterio/lib/RateLimiter");
@@ -49,7 +50,7 @@ async function saveDatabase(masterConfig, items, logger) {
let file = path.resolve(masterConfig.get("master.database_directory"), "items.json");
logger.verbose(`writing ${file}`);
let content = JSON.stringify(items.serialize());
await fs.outputFile(file, content);
await libFileOps.safeOutputFile(file, content);
} else if (items) {
logger.error(`Item database too large, not saving (${items.size})`);
}