diff options
author | Florian Dold <florian@dold.me> | 2024-03-08 10:30:23 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-03-08 18:23:10 +0100 |
commit | 0a2540d676904e804544b95959bae223e42bc0c1 (patch) | |
tree | 71bdb3d111da72a95afdb638ef36cc13b0c30635 /packages/taler-wallet-core/src/withdraw.ts | |
parent | ddd32a690bd13b1eb1aef1356a1d59fd64e254bf (diff) | |
download | wallet-core-0a2540d676904e804544b95959bae223e42bc0c1.tar.xz |
wallet-core: notification-based waiting for dependent transactions instead of long-polling
Diffstat (limited to 'packages/taler-wallet-core/src/withdraw.ts')
-rw-r--r-- | packages/taler-wallet-core/src/withdraw.ts | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts index 0f70479a5..f27e9e132 100644 --- a/packages/taler-wallet-core/src/withdraw.ts +++ b/packages/taler-wallet-core/src/withdraw.ts @@ -95,10 +95,6 @@ import { throwUnexpectedRequestError, } from "@gnu-taler/taler-util/http"; import { - selectForcedWithdrawalDenominations, - selectWithdrawalDenominations, -} from "./denomSelection.js"; -import { PendingTaskType, TaskIdStr, TaskRunResult, @@ -127,6 +123,10 @@ import { WithdrawalRecordType, timestampPreciseToDb, } from "./db.js"; +import { + selectForcedWithdrawalDenominations, + selectWithdrawalDenominations, +} from "./denomSelection.js"; import { isWithdrawableDenom } from "./denominations.js"; import { ReadyExchangeSummary, @@ -1935,7 +1935,8 @@ export async function getWithdrawalDetailsForUri( uri: talerWithdrawUri, }); } - }).finally(() => { + }) + .finally(() => { ongoingChecks[talerWithdrawUri] = false; }); } @@ -2703,6 +2704,7 @@ async function waitWithdrawalRegistered( wex: WalletExecutionContext, ctx: WithdrawTransactionContext, ): Promise<void> { + // FIXME: Doesn't support cancellation yet // FIXME: We should use Symbol.dispose magic here for cleanup! const withdrawalNotifFlag = new AsyncFlag(); @@ -2914,3 +2916,77 @@ export async function createManualWithdrawal( transactionId: ctx.transactionId, }; } + +/** + * Wait until a refresh operation is final. + */ +export async function waitWithdrawalFinal( + wex: WalletExecutionContext, + withdrawalGroupId: string, +): Promise<void> { + const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId); + wex.taskScheduler.startShepherdTask(ctx.taskId); + + // FIXME: Clean up using the new JS "using" / Symbol.dispose syntax. + const withdrawalNotifFlag = new AsyncFlag(); + // Raise purchaseNotifFlag whenever we get a notification + // about our refresh. + const cancelNotif = wex.ws.addNotificationListener((notif) => { + if ( + notif.type === NotificationType.TransactionStateTransition && + notif.transactionId === ctx.transactionId + ) { + withdrawalNotifFlag.raise(); + } + }); + const unregisterOnCancelled = wex.cancellationToken.onCancelled(() => { + cancelNotif(); + withdrawalNotifFlag.raise(); + }); + + try { + await internalWaitWithdrawalFinal(ctx, withdrawalNotifFlag); + } catch (e) { + unregisterOnCancelled(); + cancelNotif(); + } +} + +async function internalWaitWithdrawalFinal( + ctx: WithdrawTransactionContext, + flag: AsyncFlag, +): Promise<void> { + while (true) { + if (ctx.wex.cancellationToken.isCancelled) { + throw Error("cancelled"); + } + + // Check if refresh is final + const res = await ctx.wex.db.runReadOnlyTx( + ["withdrawalGroups", "operationRetries"], + async (tx) => { + return { + wg: await tx.withdrawalGroups.get(ctx.withdrawalGroupId), + }; + }, + ); + const { wg } = res; + if (!wg) { + // Must've been deleted, we consider that final. + return; + } + switch (wg.status) { + case WithdrawalGroupStatus.AbortedBank: + case WithdrawalGroupStatus.AbortedExchange: + case WithdrawalGroupStatus.Done: + case WithdrawalGroupStatus.FailedAbortingBank: + case WithdrawalGroupStatus.FailedBankAborted: + // Transaction is final + return; + } + + // Wait for the next transition + await flag.wait(); + flag.reset(); + } +} |