diff options
author | Florian Dold <florian@dold.me> | 2023-04-24 20:24:23 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-04-24 20:30:01 +0200 |
commit | e4407f825960554659af276d88eb54cc4e5fde9f (patch) | |
tree | 9ce7e6841254debd508e5489908ccac7518449f4 /packages/taler-wallet-core/src/operations/refresh.ts | |
parent | 974cd02066edc1a5b8279931d6b019f667051409 (diff) |
-refunds for deposit aborts
Diffstat (limited to 'packages/taler-wallet-core/src/operations/refresh.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/refresh.ts | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index 3122c9685..748c929c2 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -49,6 +49,9 @@ import { TalerErrorCode, TalerErrorDetail, TalerProtocolTimestamp, + TransactionMajorState, + TransactionState, + TransactionType, URL, } from "@gnu-taler/taler-util"; import { TalerCryptoInterface } from "../crypto/cryptoImplementation.js"; @@ -80,13 +83,19 @@ import { import { checkDbInvariant } from "../util/invariants.js"; import { GetReadWriteAccess } from "../util/query.js"; import { + constructTaskIdentifier, OperationAttemptResult, OperationAttemptResultType, } from "../util/retries.js"; import { makeCoinAvailable } from "./common.js"; import { updateExchangeFromUrl } from "./exchanges.js"; import { selectWithdrawalDenominations } from "../util/coinSelection.js"; -import { isWithdrawableDenom, WalletConfig } from "../index.js"; +import { + isWithdrawableDenom, + PendingTaskType, + WalletConfig, +} from "../index.js"; +import { constructTransactionIdentifier } from "./transactions.js"; const logger = new Logger("refresh.ts"); @@ -1115,3 +1124,128 @@ export async function autoRefresh( }); return OperationAttemptResult.finishedEmpty(); } + +export function computeRefreshTransactionStatus( + rg: RefreshGroupRecord, +): TransactionState { + switch (rg.operationStatus) { + case RefreshOperationStatus.Finished: + return { + major: TransactionMajorState.Done, + }; + case RefreshOperationStatus.FinishedWithError: + return { + major: TransactionMajorState.Failed, + }; + case RefreshOperationStatus.Pending: + return { + major: TransactionMajorState.Pending, + }; + case RefreshOperationStatus.Suspended: + return { + major: TransactionMajorState.Suspended, + }; + } +} + +export async function suspendRefreshGroup( + ws: InternalWalletState, + refreshGroupId: string, +): Promise<void> { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.Refresh, + refreshGroupId, + }); + const retryTag = constructTaskIdentifier({ + tag: PendingTaskType.Refresh, + refreshGroupId, + }); + let res = await ws.db + .mktx((x) => [x.refreshGroups]) + .runReadWrite(async (tx) => { + const dg = await tx.refreshGroups.get(refreshGroupId); + if (!dg) { + logger.warn( + `can't suspend refresh group, refreshGroupId=${refreshGroupId} not found`, + ); + return undefined; + } + const oldState = computeRefreshTransactionStatus(dg); + switch (dg.operationStatus) { + case RefreshOperationStatus.Finished: + return undefined; + case RefreshOperationStatus.Pending: { + dg.operationStatus = RefreshOperationStatus.Suspended; + await tx.refreshGroups.put(dg); + return { + oldTxState: oldState, + newTxState: computeRefreshTransactionStatus(dg), + }; + } + case RefreshOperationStatus.Suspended: + return undefined; + } + return undefined; + }); + if (res) { + ws.notify({ + type: NotificationType.TransactionStateTransition, + transactionId, + oldTxState: res.oldTxState, + newTxState: res.newTxState, + }); + } +} + +export async function resumeRefreshGroup( + ws: InternalWalletState, + refreshGroupId: string, +): Promise<void> { + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.Refresh, + refreshGroupId, + }); + let res = await ws.db + .mktx((x) => [x.refreshGroups]) + .runReadWrite(async (tx) => { + const dg = await tx.refreshGroups.get(refreshGroupId); + if (!dg) { + logger.warn( + `can't resume refresh group, refreshGroupId=${refreshGroupId} not found`, + ); + return; + } + const oldState = computeRefreshTransactionStatus(dg); + switch (dg.operationStatus) { + case RefreshOperationStatus.Finished: + return; + case RefreshOperationStatus.Pending: { + return; + } + case RefreshOperationStatus.Suspended: + dg.operationStatus = RefreshOperationStatus.Pending; + await tx.refreshGroups.put(dg); + return { + oldTxState: oldState, + newTxState: computeRefreshTransactionStatus(dg), + }; + } + return undefined; + }); + ws.latch.trigger(); + if (res) { + ws.notify({ + type: NotificationType.TransactionStateTransition, + transactionId, + oldTxState: res.oldTxState, + newTxState: res.newTxState, + }); + } +} + +export async function abortRefreshGroup( + ws: InternalWalletState, + refreshGroupId: string, +): Promise<void> { + throw Error("can't abort refresh groups."); +} |