taler-typescript-core

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

commit 2e2482c01062e3edc40e4cafd2fea85d08f38995
parent 8ab16dd800c53dcaf827d455ed96517be7470e4b
Author: Florian Dold <florian@dold.me>
Date:   Thu, 16 Jul 2026 15:57:15 +0200

wallet-core: support retryProgressTokenNow for getExchangeTos

Diffstat:
Mpackages/taler-util/src/timer.ts | 18++++++++++++++----
Mpackages/taler-wallet-core/src/exchanges.ts | 21++++++++++++++++++++-
Mpackages/taler-wallet-core/src/progress.ts | 3+--
Mpackages/taler-wallet-core/src/wallet.ts | 19++++++++++---------
4 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/packages/taler-util/src/timer.ts b/packages/taler-util/src/timer.ts @@ -24,7 +24,7 @@ /** * Imports. */ -import { Logger, Duration } from "@gnu-taler/taler-util"; +import { CancellationToken, Duration, Logger } from "@gnu-taler/taler-util"; const logger = new Logger("timer.ts"); @@ -160,11 +160,21 @@ export class TimerGroup { } } - resolveAfter(delayMs: Duration): Promise<void> { - return new Promise<void>((resolve, reject) => { + resolveAfter( + delayMs: Duration, + cancellationToken?: CancellationToken, + ): Promise<boolean> { + return new Promise<boolean>((resolve, reject) => { + let unregisterCt: (() => void) | undefined; + if (cancellationToken != null) { + unregisterCt = cancellationToken.onCancelled(() => { + resolve(false); + }); + } if (delayMs.d_ms !== "forever") { this.after(delayMs.d_ms, () => { - resolve(); + unregisterCt?.(); + resolve(true); }); } }); diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -2725,10 +2725,19 @@ export async function getExchangeTos( acceptLanguage?: string, progressContext?: ProgressContext, ): Promise<GetExchangeTosResult> { + if (progressContext) { + progressContext.onRetryNow = async () => { + await resetExchangeRetries(wex, exchangeBaseUrl); + }; + } const exch = await fetchFreshExchange(wex, exchangeBaseUrl, { progressContext, }); + if (progressContext) { + delete progressContext.onRetryNow; + } + switch (exch.tosStatus) { case ExchangeTosStatus.MissingTos: return { @@ -2760,6 +2769,13 @@ export async function getExchangeTos( {}, ); } + const cts = CancellationToken.create(); + if (progressContext != null) { + progressContext.onRetryNow = async () => { + cts.cancel(); + retryCount = 0; + }; + } try { const tosRes = await exchangeClient.getTermsText({ acceptFormats: acceptedFormat, @@ -2796,7 +2812,10 @@ export async function getExchangeTos( retryCounter: retryCount, }); retryCount++; - await wex.ws.timerGroup.resolveAfter(delay); + const didWait = await wex.ws.timerGroup.resolveAfter(delay, cts.token); + if (!didWait) { + logger.info(`timeout cancelled, retrying immediately`); + } } if (tosDownload != null) { diff --git a/packages/taler-wallet-core/src/progress.ts b/packages/taler-wallet-core/src/progress.ts @@ -61,7 +61,6 @@ export async function withMaybeProgressContext<T>( wex: WalletExecutionContext, op: string, tok: string | undefined, - onRetryNow: undefined | (() => Promise<void>), f: (pc?: ProgressContext) => Promise<T>, ): Promise<T> { if (tok != null) { @@ -69,7 +68,7 @@ export async function withMaybeProgressContext<T>( operation: op, progressToken: tok, finished: false, - onRetryNow, + onRetryNow: undefined, cts: wex.cts, progressContextId: progressContextCounter++, }; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -370,11 +370,6 @@ import { } from "./exchanges.js"; import { convertDepositAmount } from "./instructedAmountConversion.js"; import { - completeAliasRegistration, - lookupAlias, - registerAlias -} from "./taldir.js" -import { addMailboxMessage, createNewMailbox, deleteMailboxMessage, @@ -439,6 +434,11 @@ import { getActiveTaskIds, } from "./shepherd.js"; import { + completeAliasRegistration, + lookupAlias, + registerAlias, +} from "./taldir.js"; +import { WithdrawTestBalanceResult, runIntegrationTest, runIntegrationTest2, @@ -928,10 +928,12 @@ async function handlePrepareWithdrawExchange( wex, "prepareWithdrawExchange", req.progressToken, - async () => { - await resetExchangeRetries(wex, exchangeBaseUrl); - }, async (pc) => { + if (pc) { + pc.onRetryNow = async () => { + await resetExchangeRetries(wex, exchangeBaseUrl); + }; + } const exchange = await fetchFreshExchange(wex, exchangeBaseUrl, { noBail: pc != null, progressContext: pc, @@ -1290,7 +1292,6 @@ async function handleGetExchangeTos( wex, "getExchangeTos", req.progressToken, - undefined, async (pc) => { return getExchangeTos( wex,