From 857a2b9dcaf64d4298027644f8e6716fa22db941 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 11 May 2020 21:47:35 +0530 Subject: perf: reserve history in separate object store --- src/operations/balance.ts | 6 ++++- src/operations/history.ts | 7 ++++- src/operations/reserves.ts | 64 ++++++++++++++++++++++++++++++++++++---------- src/operations/withdraw.ts | 2 +- 4 files changed, 63 insertions(+), 16 deletions(-) (limited to 'src/operations') diff --git a/src/operations/balance.ts b/src/operations/balance.ts index b5c1ec79e..6f9135028 100644 --- a/src/operations/balance.ts +++ b/src/operations/balance.ts @@ -145,7 +145,7 @@ export async function getBalances( ): Promise { 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 669a6cf85..1271c56ef 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 a3c6d56a4..2bbb085d5 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 { - 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 36b9f1c0f..e1c4ed57c 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( -- cgit v1.2.3