make db file writes atomic

This commit is contained in:
Florian Dold 2020-09-06 16:26:27 +05:30
parent e0c10a06b1
commit 9cb0409cfd
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B

View File

@ -58,6 +58,20 @@ export interface DefaultNodeWalletArgs {
httpLib?: HttpRequestLibrary; httpLib?: HttpRequestLibrary;
} }
/**
* Generate a random alphanumeric ID. Does *not* use cryptographically
* secure randomness.
*/
function makeId(length: number): string {
let result = "";
const characters =
"abcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
/** /**
* Get a wallet instance with default settings for node. * Get a wallet instance with default settings for node.
*/ */
@ -77,7 +91,13 @@ export async function getDefaultNodeWallet(
const dbContent = JSON.parse(dbContentStr); const dbContent = JSON.parse(dbContentStr);
myBackend.importDump(dbContent); myBackend.importDump(dbContent);
} catch (e) { } catch (e) {
logger.warn("could not read wallet file"); const code: string = e.code;
if (code === "ENOENT") {
logger.trace("wallet file doesn't exist yet");
} else {
logger.error("could not open wallet database file");
throw e;
}
} }
myBackend.afterCommitCallback = async () => { myBackend.afterCommitCallback = async () => {
@ -85,10 +105,13 @@ export async function getDefaultNodeWallet(
if (args.persistentStoragePath === undefined) { if (args.persistentStoragePath === undefined) {
return; return;
} }
const tmpPath = `${args.persistentStoragePath}-${makeId(5)}.tmp`;
const dbContent = myBackend.exportDump(); const dbContent = myBackend.exportDump();
fs.writeFileSync(storagePath, JSON.stringify(dbContent, undefined, 2), { fs.writeFileSync(tmpPath, JSON.stringify(dbContent, undefined, 2), {
encoding: "utf-8", encoding: "utf-8",
}); });
// Atomically move the temporary file onto the DB path.
fs.renameSync(tmpPath, args.persistentStoragePath);
}; };
} }
@ -106,7 +129,7 @@ export async function getDefaultNodeWallet(
const myVersionChange = (): Promise<void> => { const myVersionChange = (): Promise<void> => {
logger.error("version change requested, should not happen"); logger.error("version change requested, should not happen");
throw Error(); throw Error("BUG: wallet DB version change event can't happen with memory IDB");
}; };
shimIndexedDB(myBridgeIdbFactory); shimIndexedDB(myBridgeIdbFactory);