gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core: open DB inside w


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: open DB inside wallet handle, back up meta DB as well
Date: Wed, 30 Aug 2023 16:51:54 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new aba173d8a wallet-core: open DB inside wallet handle, back up meta DB 
as well
aba173d8a is described below

commit aba173d8a906fa0ede0c3660bd37b11fb7a6a127
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Aug 30 16:51:51 2023 +0200

    wallet-core: open DB inside wallet handle, back up meta DB as well
---
 packages/taler-wallet-core/src/db.ts               | 78 +++++++++++++++-------
 packages/taler-wallet-core/src/host-impl.node.ts   | 11 +--
 packages/taler-wallet-core/src/host-impl.qtart.ts  | 20 ++----
 .../taler-wallet-core/src/internal-wallet-state.ts |  4 ++
 packages/taler-wallet-core/src/util/query.ts       |  2 +-
 packages/taler-wallet-core/src/wallet.ts           | 50 ++++++++++----
 .../taler-wallet-webextension/src/wxBackend.ts     |  9 +--
 7 files changed, 104 insertions(+), 70 deletions(-)

diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index ba5295dda..efc0333f4 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -104,7 +104,7 @@ import { RetryInfo, TaskIdentifiers } from 
"./operations/common.js";
  * for all previous versions must be written, which should be
  * avoided.
  */
-export const TALER_DB_NAME = "taler-wallet-main-v9";
+export const TALER_WALLET_MAIN_DB_NAME = "taler-wallet-main-v9";
 
 /**
  * Name of the metadata database.  This database is used
@@ -112,7 +112,7 @@ export const TALER_DB_NAME = "taler-wallet-main-v9";
  *
  * (Minor migrations are handled via upgrade transactions.)
  */
-export const TALER_META_DB_NAME = "taler-wallet-meta";
+export const TALER_WALLET_META_DB_NAME = "taler-wallet-meta";
 
 export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
 
@@ -2806,25 +2806,36 @@ export interface DbDump {
   };
 }
 
-export function exportDb(db: IDBDatabase): Promise<DbDump> {
-  const dbDump: DbDump = {
-    databases: {},
-  };
+export async function exportSingleDb(
+  idb: IDBFactory,
+  dbName: string,
+): Promise<DbDumpDatabase> {
+  const myDb = await openDatabase(
+    idb,
+    dbName,
+    undefined,
+    () => {
+      // May not happen, since we're not requesting a specific version
+      throw Error("unexpected version change");
+    },
+    () => {
+      logger.info("unexpected onupgradeneeded");
+    },
+  );
 
-  const walletDb: DbDumpDatabase = {
-    version: db.version,
+  const singleDbDump: DbDumpDatabase = {
+    version: myDb.version,
     stores: {},
   };
-  dbDump.databases[db.name] = walletDb;
 
   return new Promise((resolve, reject) => {
-    const tx = db.transaction(Array.from(db.objectStoreNames));
+    const tx = myDb.transaction(Array.from(myDb.objectStoreNames));
     tx.addEventListener("complete", () => {
-      resolve(dbDump);
+      resolve(singleDbDump);
     });
     // tslint:disable-next-line:prefer-for-of
-    for (let i = 0; i < db.objectStoreNames.length; i++) {
-      const name = db.objectStoreNames[i];
+    for (let i = 0; i < myDb.objectStoreNames.length; i++) {
+      const name = myDb.objectStoreNames[i];
       const store = tx.objectStore(name);
       const storeDump: DbStoreDump = {
         autoIncrement: store.autoIncrement,
@@ -2842,7 +2853,7 @@ export function exportDb(db: IDBDatabase): 
Promise<DbDump> {
           unique: index.unique,
         };
       }
-      walletDb.stores[name] = storeDump;
+      singleDbDump.stores[name] = storeDump;
       store.openCursor().addEventListener("success", (e: Event) => {
         const cursor = (e.target as any).result;
         if (cursor) {
@@ -2862,6 +2873,23 @@ export function exportDb(db: IDBDatabase): 
Promise<DbDump> {
   });
 }
 
+export async function exportDb(idb: IDBFactory): Promise<DbDump> {
+  const dbDump: DbDump = {
+    databases: {},
+  };
+
+  dbDump.databases[TALER_WALLET_META_DB_NAME] = await exportSingleDb(
+    idb,
+    TALER_WALLET_META_DB_NAME,
+  );
+  dbDump.databases[TALER_WALLET_MAIN_DB_NAME] = await exportSingleDb(
+    idb,
+    TALER_WALLET_MAIN_DB_NAME,
+  );
+
+  return dbDump;
+}
+
 export interface DatabaseDump {
   name: string;
   stores: { [s: string]: any };
@@ -2902,13 +2930,13 @@ export async function importDb(db: IDBDatabase, object: 
any): Promise<void> {
     // looks like a IDBDatabase
     const someDatabase = object.databases;
 
-    if (TALER_META_DB_NAME in someDatabase) {
+    if (TALER_WALLET_META_DB_NAME in someDatabase) {
       //looks like a taler database
       const currentMainDbValue =
-        someDatabase[TALER_META_DB_NAME].objectStores.metaConfig.records[0]
-          .value.value;
+        someDatabase[TALER_WALLET_META_DB_NAME].objectStores.metaConfig
+          .records[0].value.value;
 
-      if (currentMainDbValue !== TALER_DB_NAME) {
+      if (currentMainDbValue !== TALER_WALLET_MAIN_DB_NAME) {
         console.log("not the current database version");
       }
 
@@ -3236,7 +3264,7 @@ export async function openTalerDatabase(
 ): Promise<DbAccess<typeof WalletStoresV1>> {
   const metaDbHandle = await openDatabase(
     idbFactory,
-    TALER_META_DB_NAME,
+    TALER_WALLET_META_DB_NAME,
     1,
     () => {},
     onMetaDbUpgradeNeeded,
@@ -3249,17 +3277,17 @@ export async function openTalerDatabase(
     .runReadWrite(async (tx) => {
       const dbVersionRecord = await tx.metaConfig.get(CURRENT_DB_CONFIG_KEY);
       if (!dbVersionRecord) {
-        currentMainVersion = TALER_DB_NAME;
+        currentMainVersion = TALER_WALLET_MAIN_DB_NAME;
         await tx.metaConfig.put({
           key: CURRENT_DB_CONFIG_KEY,
-          value: TALER_DB_NAME,
+          value: TALER_WALLET_MAIN_DB_NAME,
         });
       } else {
         currentMainVersion = dbVersionRecord.value;
       }
     });
 
-  if (currentMainVersion !== TALER_DB_NAME) {
+  if (currentMainVersion !== TALER_WALLET_MAIN_DB_NAME) {
     switch (currentMainVersion) {
       case "taler-wallet-main-v2":
       case "taler-wallet-main-v3":
@@ -3275,7 +3303,7 @@ export async function openTalerDatabase(
           .runReadWrite(async (tx) => {
             await tx.metaConfig.put({
               key: CURRENT_DB_CONFIG_KEY,
-              value: TALER_DB_NAME,
+              value: TALER_WALLET_MAIN_DB_NAME,
             });
           });
         break;
@@ -3288,7 +3316,7 @@ export async function openTalerDatabase(
 
   const mainDbHandle = await openDatabase(
     idbFactory,
-    TALER_DB_NAME,
+    TALER_WALLET_MAIN_DB_NAME,
     WALLET_DB_MINOR_VERSION,
     onVersionChange,
     onTalerDbUpgradeNeeded,
@@ -3305,7 +3333,7 @@ export async function deleteTalerDatabase(
   idbFactory: IDBFactory,
 ): Promise<void> {
   return new Promise((resolve, reject) => {
-    const req = idbFactory.deleteDatabase(TALER_DB_NAME);
+    const req = idbFactory.deleteDatabase(TALER_WALLET_MAIN_DB_NAME);
     req.onerror = () => reject(req.error);
     req.onsuccess = () => resolve();
   });
diff --git a/packages/taler-wallet-core/src/host-impl.node.ts 
b/packages/taler-wallet-core/src/host-impl.node.ts
index 6a4f21d79..0b6539306 100644
--- a/packages/taler-wallet-core/src/host-impl.node.ts
+++ b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -139,13 +139,6 @@ export async function createNativeWalletHost2(
     });
   }
 
-  const myVersionChange = (): Promise<void> => {
-    logger.error("version change requested, should not happen");
-    throw Error(
-      "BUG: wallet DB version change event can't happen with memory IDB",
-    );
-  };
-
   let dbResp: MakeDbResult;
 
   if (args.persistentStoragePath 
&&args.persistentStoragePath.endsWith(".json")) {
@@ -160,8 +153,6 @@ export async function createNativeWalletHost2(
 
   shimIndexedDB(dbResp.idbFactory);
 
-  const myDb = await openTalerDatabase(myIdbFactory, myVersionChange);
-
   let workerFactory;
   const cryptoWorkerType = args.cryptoWorkerType ?? "node-worker-thread";
   if (cryptoWorkerType === "sync") {
@@ -189,7 +180,7 @@ export async function createNativeWalletHost2(
   const timer = new SetTimeoutTimerAPI();
 
   const w = await Wallet.create(
-    myDb,
+    myIdbFactory,
     myHttpLib,
     timer,
     workerFactory,
diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts 
b/packages/taler-wallet-core/src/host-impl.qtart.ts
index 720f5affb..81dbe0acd 100644
--- a/packages/taler-wallet-core/src/host-impl.qtart.ts
+++ b/packages/taler-wallet-core/src/host-impl.qtart.ts
@@ -110,7 +110,7 @@ async function makeSqliteDb(
       return {
         ...myBackend.accessStats,
         primitiveStatements: numStmt,
-      }
+      };
     },
     idbFactory: myBridgeIdbFactory,
   };
@@ -167,12 +167,15 @@ export async function createNativeWalletHost2(
 
   let dbResp: MakeDbResult;
 
-  if (args.persistentStoragePath && 
args.persistentStoragePath.endsWith(".json")) {
+  if (
+    args.persistentStoragePath &&
+    args.persistentStoragePath.endsWith(".json")
+  ) {
     logger.info("using JSON file DB backend (slow!)");
     dbResp = await makeFileDb(args);
   } else {
     logger.info("using sqlite3 DB backend (experimental!)");
-    dbResp = await makeSqliteDb(args)
+    dbResp = await makeSqliteDb(args);
   }
 
   const myIdbFactory: IDBFactory = dbResp.idbFactory as any as IDBFactory;
@@ -189,22 +192,13 @@ export async function createNativeWalletHost2(
     });
   }
 
-  const myVersionChange = (): Promise<void> => {
-    logger.error("version change requested, should not happen");
-    throw Error(
-      "BUG: wallet DB version change event can't happen with memory IDB",
-    );
-  };
-
-  const myDb = await openTalerDatabase(myIdbFactory, myVersionChange);
-
   let workerFactory;
   workerFactory = new SynchronousCryptoWorkerFactoryPlain();
 
   const timer = new SetTimeoutTimerAPI();
 
   const w = await Wallet.create(
-    myDb,
+    myIdbFactory,
     myHttpLib,
     timer,
     workerFactory,
diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts 
b/packages/taler-wallet-core/src/internal-wallet-state.ts
index 76aee05bd..a189c9cb3 100644
--- a/packages/taler-wallet-core/src/internal-wallet-state.ts
+++ b/packages/taler-wallet-core/src/internal-wallet-state.ts
@@ -54,6 +54,7 @@ import {
 } from "./util/query.js";
 import { TimerGroup } from "./util/timer.js";
 import { WalletConfig } from "./wallet-api-types.js";
+import { IDBFactory } from "@gnu-taler/idb-bridge";
 
 export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
 export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
@@ -203,6 +204,9 @@ export interface InternalWalletState {
     denomPubHash: string,
   ): Promise<DenominationInfo | undefined>;
 
+  ensureWalletDbOpen(): Promise<void>;
+
+  idb: IDBFactory;
   db: DbAccess<typeof WalletStoresV1>;
   http: HttpRequestLibrary;
 
diff --git a/packages/taler-wallet-core/src/util/query.ts 
b/packages/taler-wallet-core/src/util/query.ts
index 71f80f8aa..eb2bddec1 100644
--- a/packages/taler-wallet-core/src/util/query.ts
+++ b/packages/taler-wallet-core/src/util/query.ts
@@ -239,7 +239,7 @@ class ResultStream<T> {
 export function openDatabase(
   idbFactory: IDBFactory,
   databaseName: string,
-  databaseVersion: number,
+  databaseVersion: number | undefined,
   onVersionChange: () => void,
   onUpgradeNeeded: (
     db: IDBDatabase,
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index c9ccda20d..9f754ed69 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -139,6 +139,7 @@ import {
   clearDatabase,
   exportDb,
   importDb,
+  openTalerDatabase,
 } from "./db.js";
 import { DevExperimentHttpLib, applyDevExperiment } from 
"./dev-experiments.js";
 import {
@@ -315,6 +316,7 @@ import {
   getMaxPeerPushAmount,
   convertWithdrawalAmount,
 } from "./util/instructedAmountConversion.js";
+import { IDBFactory } from "@gnu-taler/idb-bridge";
 
 const logger = new Logger("wallet.ts");
 
@@ -1539,7 +1541,7 @@ async function dispatchRequestInternal<Op extends 
WalletApiOperation>(
       return {};
     }
     case WalletApiOperation.ExportDb: {
-      const dbDump = await exportDb(ws.db.idbHandle());
+      const dbDump = await exportDb(ws.idb);
       return dbDump;
     }
     case WalletApiOperation.ImportDb: {
@@ -1654,14 +1656,14 @@ export class Wallet {
   private _client: WalletCoreApiClient | undefined;
 
   private constructor(
-    db: DbAccess<typeof WalletStoresV1>,
+    idb: IDBFactory,
     http: HttpRequestLibrary,
     timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
     config?: WalletConfigParameter,
   ) {
     this.ws = new InternalWalletStateImpl(
-      db,
+      idb,
       http,
       timer,
       cryptoWorkerFactory,
@@ -1677,13 +1679,13 @@ export class Wallet {
   }
 
   static async create(
-    db: DbAccess<typeof WalletStoresV1>,
+    idb: IDBFactory,
     http: HttpRequestLibrary,
     timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
     config?: WalletConfigParameter,
   ): Promise<Wallet> {
-    const w = new Wallet(db, http, timer, cryptoWorkerFactory, config);
+    const w = new Wallet(idb, http, timer, cryptoWorkerFactory, config);
     w._client = await getClientFromWalletState(w.ws);
     return w;
   }
@@ -1725,19 +1727,22 @@ export class Wallet {
     this.ws.stop();
   }
 
-  runPending(): Promise<void> {
+  async runPending(): Promise<void> {
+    await this.ws.ensureWalletDbOpen();
     return runPending(this.ws);
   }
 
-  runTaskLoop(opts?: RetryLoopOpts): Promise<TaskLoopResult> {
+  async runTaskLoop(opts?: RetryLoopOpts): Promise<TaskLoopResult> {
+    await this.ws.ensureWalletDbOpen();
     return runTaskLoop(this.ws, opts);
   }
 
-  handleCoreApiRequest(
+  async handleCoreApiRequest(
     operation: string,
     id: string,
     payload: unknown,
   ): Promise<CoreApiResponse> {
+    await this.ws.ensureWalletDbOpen();
     return handleCoreApiRequest(this.ws, operation, id, payload);
   }
 }
@@ -1801,12 +1806,17 @@ class InternalWalletStateImpl implements 
InternalWalletState {
 
   config: Readonly<WalletConfig>;
 
+  private _db: DbAccess<typeof WalletStoresV1> | undefined = undefined;
+
+  get db(): DbAccess<typeof WalletStoresV1> {
+    if (!this._db) {
+      throw Error("db not initialized");
+    }
+    return this._db;
+  }
+
   constructor(
-    // FIXME: Make this a getter and make
-    // the actual value nullable.
-    // Check if we are in a DB migration / garbage collection
-    // and throw an error in that case.
-    public db: DbAccess<typeof WalletStoresV1>,
+    public idb: IDBFactory,
     public http: HttpRequestLibrary,
     public timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
@@ -1821,6 +1831,20 @@ class InternalWalletStateImpl implements 
InternalWalletState {
     }
   }
 
+  async ensureWalletDbOpen(): Promise<void> {
+    if (this._db) {
+      return;
+    }
+    const myVersionChange = (): Promise<void> => {
+      logger.error("version change requested, should not happen");
+      throw Error(
+        "BUG: wallet DB version change event can't happen with memory IDB",
+      );
+    };
+    const myDb = await openTalerDatabase(this.idb, myVersionChange);
+    this._db = myDb;
+  }
+
   async getTransactionState(
     ws: InternalWalletState,
     tx: GetReadOnlyAccess<typeof WalletStoresV1>,
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index 95af1a3a4..f071d78df 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -298,13 +298,6 @@ async function reinitWallet(): Promise<void> {
   }
   currentDatabase = undefined;
   // setBadgeText({ text: "" });
-  try {
-    currentDatabase = await openTalerDatabase(indexedDB as any, reinitWallet);
-  } catch (e) {
-    logger.error("could not open database", e);
-    walletInit.reject(e);
-    return;
-  }
   let httpLib;
   let cryptoWorker;
   let timer;
@@ -325,7 +318,7 @@ async function reinitWallet(): Promise<void> {
   const settings = await platform.getSettingsFromStorage();
   logger.info("Setting up wallet");
   const wallet = await Wallet.create(
-    currentDatabase,
+    indexedDB as any,
     httpLib,
     timer,
     cryptoWorker,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]