aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/refresh.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/refresh.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts136
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.");
+}