taler-typescript-core

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

commit b57f850195d951db1de88c97e15a669e5d2e805b
parent 7e33bc8c4ad2bb8479a6dd66212613963d4d6b08
Author: Florian Dold <florian@dold.me>
Date:   Tue, 14 Jan 2025 21:05:11 +0100

wallet-core: only transition exchange entry if update is really required

Diffstat:
Mpackages/taler-wallet-core/src/exchanges.ts | 150++++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 75 insertions(+), 75 deletions(-)

diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -1155,95 +1155,95 @@ async function startUpdateExchangeEntry( return provideExchangeRecordInTx(wex.ws, tx, exchangeBaseUrl); }, ); - - logger.trace("created exchange record"); - if (notification) { wex.ws.notify(notification); } - const { oldExchangeState, newExchangeState, taskId } = - await wex.db.runReadWriteTx( - { storeNames: ["exchanges", "operationRetries", "denominations"] }, - async (tx) => { - const r = await tx.exchanges.get(exchangeBaseUrl); - if (!r) { - throw Error("exchange not found"); - } - - // FIXME: Do not transition at all if the exchange info is recent enough - // and the request is not forced. + const res = await wex.db.runReadWriteTx( + { storeNames: ["exchanges", "operationRetries", "denominations"] }, + async (tx) => { + const r = await tx.exchanges.get(exchangeBaseUrl); + if (!r) { + throw Error("exchange not found"); + } - const oldExchangeState = getExchangeState(r); - switch (r.updateStatus) { - case ExchangeEntryDbUpdateStatus.UnavailableUpdate: - r.cachebreakNextUpdate = options.forceUpdate; - break; - case ExchangeEntryDbUpdateStatus.Suspended: - r.cachebreakNextUpdate = options.forceUpdate; - break; - case ExchangeEntryDbUpdateStatus.ReadyUpdate: { - const outdated = await checkExchangeEntryOutdated( - wex, - tx, - exchangeBaseUrl, - ); - if (outdated) { - r.updateStatus = ExchangeEntryDbUpdateStatus.OutdatedUpdate; - } else { - r.updateStatus = ExchangeEntryDbUpdateStatus.ReadyUpdate; - } - r.cachebreakNextUpdate = options.forceUpdate; - break; + const oldExchangeState = getExchangeState(r); + switch (r.updateStatus) { + case ExchangeEntryDbUpdateStatus.UnavailableUpdate: + r.cachebreakNextUpdate = options.forceUpdate; + break; + case ExchangeEntryDbUpdateStatus.Suspended: + r.cachebreakNextUpdate = options.forceUpdate; + break; + case ExchangeEntryDbUpdateStatus.ReadyUpdate: { + const outdated = await checkExchangeEntryOutdated( + wex, + tx, + exchangeBaseUrl, + ); + if (outdated) { + r.updateStatus = ExchangeEntryDbUpdateStatus.OutdatedUpdate; + } else { + r.updateStatus = ExchangeEntryDbUpdateStatus.ReadyUpdate; } - case ExchangeEntryDbUpdateStatus.OutdatedUpdate: - r.cachebreakNextUpdate = options.forceUpdate; - break; - case ExchangeEntryDbUpdateStatus.Ready: { - const nextUpdateTimestamp = AbsoluteTime.fromPreciseTimestamp( - timestampPreciseFromDb(r.nextUpdateStamp), - ); - // Only update if entry is outdated or update is forced. - if ( - options.forceUpdate || - AbsoluteTime.isExpired(nextUpdateTimestamp) - ) { - const outdated = await checkExchangeEntryOutdated( - wex, - tx, - exchangeBaseUrl, - ); - if (outdated) { - r.updateStatus = ExchangeEntryDbUpdateStatus.OutdatedUpdate; - } else { - r.updateStatus = ExchangeEntryDbUpdateStatus.ReadyUpdate; - } - r.cachebreakNextUpdate = options.forceUpdate; - } - break; + r.cachebreakNextUpdate = options.forceUpdate; + break; + } + case ExchangeEntryDbUpdateStatus.OutdatedUpdate: + r.cachebreakNextUpdate = options.forceUpdate; + break; + case ExchangeEntryDbUpdateStatus.Ready: { + const nextUpdateTimestamp = AbsoluteTime.fromPreciseTimestamp( + timestampPreciseFromDb(r.nextUpdateStamp), + ); + // Only update if entry is outdated or update is forced. + if ( + !( + options.forceUpdate || AbsoluteTime.isExpired(nextUpdateTimestamp) + ) + ) { + return undefined; } - case ExchangeEntryDbUpdateStatus.Initial: - r.cachebreakNextUpdate = options.forceUpdate; - r.updateStatus = ExchangeEntryDbUpdateStatus.InitialUpdate; - break; - case ExchangeEntryDbUpdateStatus.InitialUpdate: - r.cachebreakNextUpdate = options.forceUpdate; - break; + const outdated = await checkExchangeEntryOutdated( + wex, + tx, + exchangeBaseUrl, + ); + if (outdated) { + r.updateStatus = ExchangeEntryDbUpdateStatus.OutdatedUpdate; + } else { + r.updateStatus = ExchangeEntryDbUpdateStatus.ReadyUpdate; + } + r.cachebreakNextUpdate = options.forceUpdate; + break; } - wex.ws.exchangeCache.clear(); - await tx.exchanges.put(r); - const newExchangeState = getExchangeState(r); - const taskId = TaskIdentifiers.forExchangeUpdate(r); - return { oldExchangeState, newExchangeState, taskId }; - }, - ); + case ExchangeEntryDbUpdateStatus.Initial: + r.cachebreakNextUpdate = options.forceUpdate; + r.updateStatus = ExchangeEntryDbUpdateStatus.InitialUpdate; + break; + case ExchangeEntryDbUpdateStatus.InitialUpdate: + r.cachebreakNextUpdate = options.forceUpdate; + break; + } + wex.ws.exchangeCache.clear(); + await tx.exchanges.put(r); + const newExchangeState = getExchangeState(r); + const taskId = TaskIdentifiers.forExchangeUpdate(r); + return { oldExchangeState, newExchangeState, taskId }; + }, + ); + if (!res) { + // Exchange entry is already good. + return; + } + const { oldExchangeState, newExchangeState, taskId } = res; wex.ws.notify({ type: NotificationType.ExchangeStateTransition, exchangeBaseUrl, newExchangeState: newExchangeState, oldExchangeState: oldExchangeState, }); - logger.info(`start update ${exchangeBaseUrl} task ${taskId}`); + logger.info(`updating exchange in task ${taskId}`); await wex.taskScheduler.resetTaskRetries(taskId); }