diff options
author | Florian Dold <florian@dold.me> | 2024-04-08 21:27:33 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-04-08 21:27:33 +0200 |
commit | 30dea85f1e2410f974f8c16e4e53d4ba1290442d (patch) | |
tree | 735a68e1ccdd559adc220b800caea565c0cc7fbe /packages/taler-wallet-core/src/wallet.ts | |
parent | 85b6213333b211bbfae9209630d8446108c4ce56 (diff) | |
download | wallet-core-30dea85f1e2410f974f8c16e4e53d4ba1290442d.tar.gz wallet-core-30dea85f1e2410f974f8c16e4e53d4ba1290442d.tar.bz2 wallet-core-30dea85f1e2410f974f8c16e4e53d4ba1290442d.zip |
wallet-core: perf, caching
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 2bafba3af..223272745 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -24,7 +24,9 @@ */ import { IDBFactory } from "@gnu-taler/idb-bridge"; import { + AbsoluteTime, ActiveTask, + AmountJson, AmountString, Amounts, AsyncCondition, @@ -35,6 +37,7 @@ import { CreateStoredBackupResponse, DeleteStoredBackupRequest, DenominationInfo, + Duration, ExchangesShortListResponse, GetCurrencySpecificationResponse, InitResponse, @@ -193,6 +196,7 @@ import { } from "./deposits.js"; import { DevExperimentHttpLib, applyDevExperiment } from "./dev-experiments.js"; import { + ReadyExchangeSummary, acceptExchangeTermsOfService, addPresetExchangeEntry, deleteExchange, @@ -356,15 +360,15 @@ export async function getDenomInfo( exchangeBaseUrl: string, denomPubHash: string, ): Promise<DenominationInfo | undefined> { - const key = `${exchangeBaseUrl}:${denomPubHash}`; - const cached = wex.ws.lookupDenomCache(key); + 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.putDenomCache(key, denomInfo); + wex.ws.denomInfoCache.put(cacheKey, denomInfo); return denomInfo; } return undefined; @@ -794,6 +798,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( }); return {}; } + case WalletApiOperation.TestingPing: { + return {}; + } case WalletApiOperation.UpdateExchangeEntry: { const req = codecForUpdateExchangeEntryRequest().decode(payload); await fetchFreshExchange(wex, req.exchangeBaseUrl, { @@ -1275,6 +1282,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( if (existingRec) { return; } + wex.ws.exchangeCache.clear(); await tx.globalCurrencyExchanges.add({ currency: req.currency, exchangeBaseUrl: req.exchangeBaseUrl, @@ -1294,6 +1302,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( if (!existingRec) { return; } + wex.ws.exchangeCache.clear(); checkDbInvariant(!!existingRec.id); await tx.globalCurrencyExchanges.delete(existingRec.id); }); @@ -1315,6 +1324,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( auditorBaseUrl: req.auditorBaseUrl, auditorPub: req.auditorPub, }); + wex.ws.exchangeCache.clear(); }); return {}; } @@ -1331,6 +1341,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( } checkDbInvariant(!!existingRec.id); await tx.globalCurrencyAuditors.delete(existingRec.id); + wex.ws.exchangeCache.clear(); }); return {}; } @@ -1664,6 +1675,44 @@ export interface DevExperimentState { blockRefreshes?: boolean; } +export class Cache<T> { + private map: Map<string, [AbsoluteTime, T]> = new Map(); + + constructor( + private maxCapacity: number, + private cacheDuration: Duration, + ) {} + + get(key: string): T | undefined { + const r = this.map.get(key); + if (!r) { + return undefined; + } + + if (AbsoluteTime.isExpired(r[0])) { + this.map.delete(key); + return undefined; + } + + return r[1]; + } + + clear(): void { + this.map.clear(); + } + + put(key: string, value: T): void { + if (this.map.size > this.maxCapacity) { + this.map.clear(); + } + const expiry = AbsoluteTime.addDuration( + AbsoluteTime.now(), + this.cacheDuration, + ); + this.map.set(key, [expiry, value]); + } +} + /** * Internal state of the wallet. * @@ -1681,7 +1730,20 @@ export class InternalWalletState { initCalled = false; - private denomCache: Map<string, DenominationInfo> = new Map(); + refreshCostCache: Cache<AmountJson> = new Cache( + 1000, + Duration.fromSpec({ minutes: 1 }), + ); + + denomInfoCache: Cache<DenominationInfo> = new Cache( + 1000, + Duration.fromSpec({ minutes: 1 }), + ); + + exchangeCache: Cache<ReadyExchangeSummary> = new Cache( + 1000, + Duration.fromSpec({ minutes: 1 }), + ); /** * Promises that are waiting for a particular resource. @@ -1710,17 +1772,6 @@ export class InternalWalletState { devExperimentState: DevExperimentState = {}; - lookupDenomCache(denomCacheKey: string): DenominationInfo | undefined { - return this.denomCache.get(denomCacheKey); - } - - putDenomCache(denomCacheKey: string, denomInfo: DenominationInfo): void { - if (this.denomCache.size > 1000) { - this.denomCache.clear(); - } - this.denomCache.set(denomCacheKey, denomInfo); - } - initWithConfig(newConfig: WalletRunConfig): void { this._config = newConfig; |