aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-09-06 16:26:27 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-09-06 16:26:27 +0530
commit9cb0409cfdb0d841a65129ac82e730be7e6d6efe (patch)
treed06587c813dd58fccb1cba7a2e312396e1cf90d5
parente0c10a06b1a1f2f91676f6846c4cf80af9e80b83 (diff)
make db file writes atomic
-rw-r--r--packages/taler-wallet-core/src/headless/helpers.ts29
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);