taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 1a12e2fc8e5d15ceba80090dc796457f22442fd9
parent 9856854690b71435536790e5f406e95624da599f
Author: Antoine A <>
Date:   Wed, 30 Apr 2025 13:06:55 +0200

wallet: clean cache logic

Diffstat:
Mpackages/taler-wallet-core/src/exchanges.ts | 4+---
Mpackages/taler-wallet-core/src/refresh.ts | 40+++++++++++++++++-----------------------
Mpackages/taler-wallet-core/src/wallet.ts | 42+++++++++++++++++++++++++++---------------
3 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -1782,9 +1782,7 @@ export async function updateExchangeFromUrlHandler( return; } - wex.ws.refreshCostCache.clear(); - wex.ws.exchangeCache.clear(); - wex.ws.denomInfoCache.clear(); + wex.ws.clearAllCaches(); const oldExchangeState = getExchangeState(r); const existingDetails = await getExchangeRecordsInternal(tx, r.baseUrl); diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts @@ -416,26 +416,21 @@ export async function getTotalRefreshCost( refreshedDenom: DenominationInfo, amountLeft: AmountJson, ): Promise<AmountJson> { - const cacheKey = `denom=${refreshedDenom.exchangeBaseUrl}/${ - refreshedDenom.denomPubHash - };left=${Amounts.stringify(amountLeft)}`; - const cacheRes = wex.ws.refreshCostCache.get(cacheKey); - if (cacheRes) { - return cacheRes; - } - const allDenoms = await getWithdrawableDenomsTx( - wex, - tx, - refreshedDenom.exchangeBaseUrl, - Amounts.currencyOf(amountLeft), - ); - const res = getTotalRefreshCostInternal( - allDenoms, - refreshedDenom, - amountLeft, - ); - wex.ws.refreshCostCache.put(cacheKey, res); - return res; + const { exchangeBaseUrl, denomPubHash } = refreshedDenom; + const key = `denom=${exchangeBaseUrl}/${denomPubHash};left=${Amounts.stringify(amountLeft)}`; + return wex.ws.refreshCostCache.getOrPut(key, async () => { + const allDenoms = await getWithdrawableDenomsTx( + wex, + tx, + exchangeBaseUrl, + Amounts.currencyOf(amountLeft), + ); + return getTotalRefreshCostInternal( + allDenoms, + refreshedDenom, + amountLeft, + ); + }) } /** @@ -455,8 +450,7 @@ export function getTotalRefreshCostInternal( amountLeft: AmountJson, ): AmountJson { logger.trace( - `computing total refresh cost, denom value ${ - refreshedDenom.value + `computing total refresh cost, denom value ${refreshedDenom.value }, amount left ${Amounts.stringify(amountLeft)}`, ); const withdrawAmount = Amounts.sub( @@ -1621,7 +1615,7 @@ async function refreshReveal( ); checkDbInvariant( car.pendingRefreshOutputCount != null && - car.pendingRefreshOutputCount > 0, + car.pendingRefreshOutputCount > 0, `no pendingRefreshOutputCount for denom ${coin.denomPubHash} age ${coin.maxAge}`, ); car.pendingRefreshOutputCount--; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -517,18 +517,15 @@ export async function getDenomInfo( exchangeBaseUrl: string, denomPubHash: string, ): Promise<DenominationInfo | undefined> { - const cacheKey = `${exchangeBaseUrl}:${denomPubHash}`; - const cached = wex.ws.denomInfoCache.get(cacheKey); - if (cached) { - return cached; - } - const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]); - if (d) { - const denomInfo = DenominationRecord.toDenomInfo(d); - wex.ws.denomInfoCache.put(cacheKey, denomInfo); - return denomInfo; - } - return undefined; + const key = `${exchangeBaseUrl}:${denomPubHash}`; + return wex.ws.denomInfoCache.getOrPut(key, async () => { + const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]); + if (d != null) { + return DenominationRecord.toDenomInfo(d); + } else { + return undefined + } + }) } /** @@ -2464,7 +2461,7 @@ async function dispatchWalletCoreApiRequest( wex = getObservedWalletExecutionContext(ws, cts.token, cts, oc); } else { oc = { - observe(evt) {}, + observe(evt) { }, }; wex = getNormalWalletExecutionContext(ws, cts.token, cts, oc); } @@ -2619,7 +2616,7 @@ export class Cache<T> { constructor( private maxCapacity: number, private cacheDuration: Duration, - ) {} + ) { } get(key: string): T | undefined { const r = this.map.get(key); @@ -2635,6 +2632,21 @@ export class Cache<T> { return r[1]; } + async getOrPut(key: string, lambda: () => Promise<T>): Promise<T>; + async getOrPut(key: string, lambda: () => Promise<T | undefined>): Promise<T | undefined>; + async getOrPut(key: string, lambda: () => Promise<T | undefined>): Promise<T | undefined> { + const cached = this.get(key); + if (cached != null) { + return cached + } else { + const computed = await lambda(); + if (computed != null) { + this.put(key, computed) + } + return computed; + } + } + clear(): void { this.map.clear(); } @@ -2655,7 +2667,7 @@ export class Cache<T> { * Implementation of triggers for the wallet DB. */ class WalletDbTriggerSpec implements TriggerSpec { - constructor(public ws: InternalWalletState) {} + constructor(public ws: InternalWalletState) { } afterCommit(info: AfterCommitInfo): void { if (info.mode !== "readwrite") {