gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 03/03: perf: reserve history in separate object stor


From: gnunet
Subject: [taler-wallet-core] 03/03: perf: reserve history in separate object store
Date: Mon, 11 May 2020 18:17:46 +0200

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

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

commit 857a2b9dcaf64d4298027644f8e6716fa22db941
Author: Florian Dold <address@hidden>
AuthorDate: Mon May 11 21:47:35 2020 +0530

    perf: reserve history in separate object store
---
 src/db.ts                  |  2 +-
 src/operations/balance.ts  |  6 ++++-
 src/operations/history.ts  |  7 ++++-
 src/operations/reserves.ts | 64 ++++++++++++++++++++++++++++++++++++----------
 src/operations/withdraw.ts |  2 +-
 src/types/dbTypes.ts       | 14 ++++++++--
 src/webex/pages/popup.tsx  |  7 +++++
 7 files changed, 83 insertions(+), 19 deletions(-)

diff --git a/src/db.ts b/src/db.ts
index efc3b78a..098767b5 100644
--- a/src/db.ts
+++ b/src/db.ts
@@ -7,7 +7,7 @@ import { openDatabase, Database, Store, Index } from 
"./util/query";
  * with each major change.  When incrementing the major version,
  * the wallet should import data from the previous version.
  */
-const TALER_DB_NAME = "taler-walletdb-v2";
+const TALER_DB_NAME = "taler-walletdb-v3";
 
 /**
  * Current database minor version, should be incremented
diff --git a/src/operations/balance.ts b/src/operations/balance.ts
index b5c1ec79..6f913502 100644
--- a/src/operations/balance.ts
+++ b/src/operations/balance.ts
@@ -145,7 +145,7 @@ export async function getBalances(
 ): Promise<WalletBalance> {
   logger.trace("starting to compute balance");
 
-  return await ws.db.runWithReadTransaction(
+  const wbal = await ws.db.runWithReadTransaction(
     [
       Stores.coins,
       Stores.refreshGroups,
@@ -157,4 +157,8 @@ export async function getBalances(
       return getBalancesInsideTransaction(ws, tx);
     },
   );
+
+  logger.trace("finished computing wallet balance");
+
+  return wbal;
 }
diff --git a/src/operations/history.ts b/src/operations/history.ts
index 669a6cf8..1271c56e 100644
--- a/src/operations/history.ts
+++ b/src/operations/history.ts
@@ -172,6 +172,7 @@ export async function getHistory(
       Stores.purchases,
       Stores.refreshGroups,
       Stores.reserves,
+      Stores.reserveHistory,
       Stores.tips,
       Stores.withdrawalGroups,
       Stores.payEvents,
@@ -384,8 +385,12 @@ export async function getHistory(
             type: ReserveType.Manual,
           };
         }
+        const hist = await tx.get(Stores.reserveHistory, reserve.reservePub);
+        if (!hist) {
+          throw Error("inconsistent database");
+        }
         const s = summarizeReserveHistory(
-          reserve.reserveTransactions,
+          hist.reserveTransactions,
           reserve.currency,
         );
         history.push({
diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts
index a3c6d56a..2bbb085d 100644
--- a/src/operations/reserves.ts
+++ b/src/operations/reserves.ts
@@ -33,8 +33,8 @@ import {
   updateRetryInfoTimeout,
   ReserveUpdatedEventRecord,
   WalletReserveHistoryItemType,
-  PlanchetRecord,
   WithdrawalSourceType,
+  ReserveHistoryRecord,
 } from "../types/dbTypes";
 import { Logger } from "../util/logging";
 import { Amounts } from "../util/amounts";
@@ -114,11 +114,15 @@ export async function createReserve(
     lastSuccessfulStatusQuery: undefined,
     retryInfo: initRetryInfo(),
     lastError: undefined,
-    reserveTransactions: [],
     currency: req.amount.currency,
   };
 
-  reserveRecord.reserveTransactions.push({
+  const reserveHistoryRecord: ReserveHistoryRecord = {
+    reservePub: keypair.pub,
+    reserveTransactions: [],
+  };
+
+  reserveHistoryRecord.reserveTransactions.push({
     type: WalletReserveHistoryItemType.Credit,
     expectedAmount: req.amount,
   });
@@ -161,7 +165,12 @@ export async function createReserve(
   const cr: CurrencyRecord = currencyRecord;
 
   const resp = await ws.db.runWithWriteTransaction(
-    [Stores.currencies, Stores.reserves, Stores.bankWithdrawUris],
+    [
+      Stores.currencies,
+      Stores.reserves,
+      Stores.reserveHistory,
+      Stores.bankWithdrawUris,
+    ],
     async (tx) => {
       // Check if we have already created a reserve for that 
bankWithdrawStatusUrl
       if (reserveRecord.bankWithdrawStatusUrl) {
@@ -188,6 +197,7 @@ export async function createReserve(
       }
       await tx.put(Stores.currencies, cr);
       await tx.put(Stores.reserves, reserveRecord);
+      await tx.put(Stores.reserveHistory, reserveHistoryRecord);
       const r: CreateReserveResponse = {
         exchange: canonExchange,
         reservePub: keypair.pub,
@@ -462,7 +472,7 @@ async function updateReserve(
   const balance = Amounts.parseOrThrow(reserveInfo.balance);
   const currency = balance.currency;
   await ws.db.runWithWriteTransaction(
-    [Stores.reserves, Stores.reserveUpdatedEvents],
+    [Stores.reserves, Stores.reserveUpdatedEvents, Stores.reserveHistory],
     async (tx) => {
       const r = await tx.get(Stores.reserves, reservePub);
       if (!r) {
@@ -472,14 +482,19 @@ async function updateReserve(
         return;
       }
 
+      const hist = await tx.get(Stores.reserveHistory, reservePub);
+      if (!hist) {
+        throw Error("inconsistent database");
+      }
+
       const newHistoryTransactions = reserveInfo.history.slice(
-        r.reserveTransactions.length,
+        hist.reserveTransactions.length,
       );
 
       const reserveUpdateId = encodeCrock(getRandomBytes(32));
 
       const reconciled = reconcileReserveHistory(
-        r.reserveTransactions,
+        hist.reserveTransactions,
         reserveInfo.history,
       );
 
@@ -514,9 +529,10 @@ async function updateReserve(
         r.retryInfo = initRetryInfo(false);
       }
       r.lastSuccessfulStatusQuery = getTimestampNow();
-      r.reserveTransactions = reconciled.updatedLocalHistory;
+      hist.reserveTransactions = reconciled.updatedLocalHistory;
       r.lastError = undefined;
       await tx.put(Stores.reserves, r);
+      await tx.put(Stores.reserveHistory, hist);
     },
   );
   ws.notify({ type: NotificationType.ReserveUpdated });
@@ -602,17 +618,29 @@ async function depleteReserve(
   ws: InternalWalletState,
   reservePub: string,
 ): Promise<void> {
-  const reserve = await ws.db.get(Stores.reserves, reservePub);
+  let reserve: ReserveRecord | undefined;
+  let hist: ReserveHistoryRecord | undefined;
+  await ws.db.runWithReadTransaction(
+    [Stores.reserves, Stores.reserveHistory],
+    async (tx) => {
+      reserve = await tx.get(Stores.reserves, reservePub);
+      hist = await tx.get(Stores.reserveHistory, reservePub);
+    },
+  );
+
   if (!reserve) {
     return;
   }
+  if (!hist) {
+    throw Error("inconsistent database");
+  }
   if (reserve.reserveStatus !== ReserveRecordStatus.WITHDRAWING) {
     return;
   }
   logger.trace(`depleting reserve ${reservePub}`);
 
   const summary = summarizeReserveHistory(
-    reserve.reserveTransactions,
+    hist.reserveTransactions,
     reserve.currency,
   );
 
@@ -674,7 +702,12 @@ async function depleteReserve(
   };
 
   const success = await ws.db.runWithWriteTransaction(
-    [Stores.withdrawalGroups, Stores.reserves, Stores.planchets],
+    [
+      Stores.withdrawalGroups,
+      Stores.reserves,
+      Stores.reserveHistory,
+      Stores.planchets,
+    ],
     async (tx) => {
       const newReserve = await tx.get(Stores.reserves, reservePub);
       if (!newReserve) {
@@ -683,8 +716,12 @@ async function depleteReserve(
       if (newReserve.reserveStatus !== ReserveRecordStatus.WITHDRAWING) {
         return false;
       }
+      const newHist = await tx.get(Stores.reserveHistory, reservePub);
+      if (!newHist) {
+        throw Error("inconsistent database");
+      }
       const newSummary = summarizeReserveHistory(
-        newReserve.reserveTransactions,
+        newHist.reserveTransactions,
         newReserve.currency,
       );
       if (
@@ -703,7 +740,7 @@ async function depleteReserve(
         const sd = denomsForWithdraw.selectedDenoms[i];
         for (let j = 0; j < sd.count; j++) {
           const amt = Amounts.add(sd.denom.value, sd.denom.feeWithdraw).amount;
-          newReserve.reserveTransactions.push({
+          newHist.reserveTransactions.push({
             type: WalletReserveHistoryItemType.Withdraw,
             expectedAmount: amt,
           });
@@ -712,6 +749,7 @@ async function depleteReserve(
       newReserve.reserveStatus = ReserveRecordStatus.DORMANT;
       newReserve.retryInfo = initRetryInfo(false);
       await tx.put(Stores.reserves, newReserve);
+      await tx.put(Stores.reserveHistory, newHist);
       await tx.put(Stores.withdrawalGroups, withdrawalRecord);
       return true;
     },
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index 36b9f1c0..e1c4ed57 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -564,7 +564,7 @@ async function processWithdrawGroupImpl(
 
   // Withdraw coins in batches.
   // The batch size is relatively large
-  await processInBatches(genWork(), 50);
+  await processInBatches(genWork(), 10);
 }
 
 export async function getExchangeWithdrawalInfo(
diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts
index 26fcca9e..4cf19a56 100644
--- a/src/types/dbTypes.ts
+++ b/src/types/dbTypes.ts
@@ -210,6 +210,11 @@ export type WalletReserveHistoryItem =
   | WalletReserveHistoryRecoupItem
   | WalletReserveHistoryClosingItem;
 
+export interface ReserveHistoryRecord {
+  reservePub: string;
+  reserveTransactions: WalletReserveHistoryItem[];
+}
+
 /**
  * A reserve record as stored in the wallet's database.
  */
@@ -295,8 +300,6 @@ export interface ReserveRecord {
    * (either talking to the bank or the exchange).
    */
   lastError: OperationError | undefined;
-
-  reserveTransactions: WalletReserveHistoryItem[];
 }
 
 /**
@@ -1639,6 +1642,12 @@ export namespace Stores {
     }
   }
 
+  class ReserveHistoryStore extends Store<ReserveHistoryRecord> {
+    constructor() {
+      super("reserveHistory", { keyPath: "reservePub" });
+    }
+  }
+
   class TipsStore extends Store<TipRecord> {
     constructor() {
       super("tips", { keyPath: "tipId" });
@@ -1725,6 +1734,7 @@ export namespace Stores {
     keyPath: "recoupGroupId",
   });
   export const reserves = new ReservesStore();
+  export const reserveHistory = new ReserveHistoryStore();
   export const purchases = new PurchasesStore();
   export const tips = new TipsStore();
   export const senderWires = new SenderWiresStore();
diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx
index 450aae4c..4d3c65b2 100644
--- a/src/webex/pages/popup.tsx
+++ b/src/webex/pages/popup.tsx
@@ -177,6 +177,7 @@ class WalletBalanceView extends React.Component<any, any> {
   private gotError = false;
   private canceler: (() => void) | undefined = undefined;
   private unmount = false;
+  private updateBalanceRunning = false;
 
   componentWillMount(): void {
     this.canceler = wxApi.onUpdateNotification(() => this.updateBalance());
@@ -192,6 +193,10 @@ class WalletBalanceView extends React.Component<any, any> {
   }
 
   async updateBalance(): Promise<void> {
+    if (this.updateBalanceRunning) {
+      return;
+    }
+    this.updateBalanceRunning = true;
     let balance: WalletBalance;
     try {
       balance = await wxApi.getBalance();
@@ -203,6 +208,8 @@ class WalletBalanceView extends React.Component<any, any> {
       console.error("could not retrieve balances", e);
       this.setState({});
       return;
+    } finally {
+      this.updateBalanceRunning = false;
     }
     if (this.unmount) {
       return;

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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