commit b445019624df3202ff392d8770bd41c13d5e1606
parent 66fafccf8ced9c1afb01ab889753167fc010bf04
Author: Florian Dold <florian@dold.me>
Date: Tue, 14 Jul 2026 22:56:27 +0200
wallet-core: cancel up old requests with same progress token, fix cleanup
Diffstat:
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/packages/taler-wallet-core/src/progress.ts b/packages/taler-wallet-core/src/progress.ts
@@ -28,11 +28,24 @@ import { WalletExecutionContext } from "./wallet.js";
const logger = new Logger("progress.ts");
export interface ProgressContext {
+ /**
+ * User-defined progress token.
+ */
progressToken: string;
+ /**
+ * Operation that this progress token is for.
+ */
operation: string;
+ /**
+ * Did the underlying request finish?
+ */
finished: boolean;
cts: CancellationToken.Source | undefined;
onRetryNow?: () => Promise<void>;
+ /**
+ * Unique counter for this progress context.
+ */
+ progressContextId: number;
}
function getProgressKey(args: {
@@ -42,6 +55,8 @@ function getProgressKey(args: {
return `${args.operation}:${encodeURIComponent(args.progressToken)}`;
}
+let progressContextCounter = 1;
+
export async function withMaybeProgressContext<T>(
wex: WalletExecutionContext,
op: string,
@@ -56,8 +71,15 @@ export async function withMaybeProgressContext<T>(
finished: false,
onRetryNow,
cts: wex.cts,
+ progressContextId: progressContextCounter++,
};
const key = getProgressKey(pc);
+ const oldPc = wex.ws.progressMap.get(key);
+ if (oldPc) {
+ oldPc.cts?.cancel();
+ oldPc.finished = true;
+ wex.ws.progressMap.delete(key);
+ }
try {
if (!wex.cts) {
logger.warn(`no cancellation source for ${op}:${tok}`);
@@ -70,8 +92,12 @@ export async function withMaybeProgressContext<T>(
pc.finished = true;
return res;
} finally {
- wex.ws.progressMap.delete(key);
- // Clean up progress token registration
+ // Clean up progress token registration,
+ // but only if it is *our* context
+ const currentPc = wex.ws.progressMap.get(key);
+ if (currentPc && currentPc.progressContextId == pc.progressContextId) {
+ wex.ws.progressMap.delete(key);
+ }
}
} else {
return await f(undefined);