diff options
author | Florian Dold <florian.dold@gmail.com> | 2020-09-06 16:26:27 +0530 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2020-09-06 16:26:27 +0530 |
commit | 9cb0409cfdb0d841a65129ac82e730be7e6d6efe (patch) | |
tree | d06587c813dd58fccb1cba7a2e312396e1cf90d5 | |
parent | e0c10a06b1a1f2f91676f6846c4cf80af9e80b83 (diff) |
make db file writes atomic
-rw-r--r-- | packages/taler-wallet-core/src/headless/helpers.ts | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/packages/taler-wallet-core/src/headless/helpers.ts b/packages/taler-wallet-core/src/headless/helpers.ts index 1141ad25e..09f0ca906 100644 --- a/packages/taler-wallet-core/src/headless/helpers.ts +++ b/packages/taler-wallet-core/src/headless/helpers.ts @@ -59,6 +59,20 @@ export interface DefaultNodeWalletArgs { } /** + * 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. */ export async function getDefaultNodeWallet( @@ -77,7 +91,13 @@ export async function getDefaultNodeWallet( const dbContent = JSON.parse(dbContentStr); myBackend.importDump(dbContent); } 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 () => { @@ -85,10 +105,13 @@ export async function getDefaultNodeWallet( if (args.persistentStoragePath === undefined) { return; } + const tmpPath = `${args.persistentStoragePath}-${makeId(5)}.tmp`; const dbContent = myBackend.exportDump(); - fs.writeFileSync(storagePath, JSON.stringify(dbContent, undefined, 2), { + fs.writeFileSync(tmpPath, JSON.stringify(dbContent, undefined, 2), { 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> => { 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); |