commit cab77b9dae0c74c299cd3c60ba2b17257bca27c6
parent ac27eec581d2dce1ab9d7ee6c9f1b96a6718ddf0
Author: Florian Dold <florian@dold.me>
Date: Wed, 3 Jun 2026 21:58:43 +0200
wallet-core: fix shepherd task cancellation
Diffstat:
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts
@@ -137,6 +137,11 @@ interface ShepherdInfo {
interruptWait: () => void;
taskState: TaskState;
+
+ /**
+ * Unique numeric identifier for the shepherd.
+ */
+ shepId: number;
}
/**
@@ -198,6 +203,8 @@ export class TaskSchedulerImpl implements TaskScheduler {
isRunning: boolean = false;
+ private shepCounter = 1;
+
constructor(private ws: InternalWalletState) {}
private async loadTasksFromDb(): Promise<void> {
@@ -304,7 +311,6 @@ export class TaskSchedulerImpl implements TaskScheduler {
logger.info(`reloading shepherd with ${tasksIds.length} existing tasks`);
for (const taskId of tasksIds) {
this.stopShepherdTask(taskId);
- this.sheps.delete(taskId);
}
await this.loadTasksFromDb();
}
@@ -333,22 +339,31 @@ export class TaskSchedulerImpl implements TaskScheduler {
logger.trace(
`Waiting for old task to complete the loop in cancel mode ${taskId}`,
);
- await oldShep.latch;
- logger.trace(`Old task ${taskId} completed in cancel mode`);
+ oldShep.cts.cancel();
}
- logger.trace(`Creating new shepherd for ${taskId}`);
const newShep: ShepherdInfo = {
cts: CancellationToken.create(),
taskState: TaskState.Running,
interruptWait: () => undefined,
+ shepId: this.shepCounter++,
};
+ logger.trace(
+ `Creating new shepherd for ${taskId} with shepId=${newShep.shepId}`,
+ );
this.sheps.set(taskId, newShep);
+ if (oldShep) {
+ await oldShep.latch;
+ logger.trace(`Old task ${taskId} completed in cancel mode`);
+ }
try {
newShep.latch = this.internalShepherdTask(taskId, newShep);
await newShep.latch;
} finally {
logger.trace(`Done shepherding ${taskId}`);
- this.sheps.delete(taskId);
+ newShep.cts.cancel();
+ if (this.sheps.get(taskId)?.shepId === newShep.shepId) {
+ this.sheps.delete(taskId);
+ }
this.iterCond.trigger();
}
}
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
@@ -1687,6 +1687,7 @@ async function handleShutdown(
wex: WalletExecutionContext,
_req: EmptyObject,
): Promise<EmptyObject> {
+ logger.info(`Shutdown requested`);
wex.ws.stop();
return {};
}