summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-03-28 23:59:16 +0200
committerFlorian Dold <florian@dold.me>2022-03-28 23:59:16 +0200
commitf5d194dfc61ae0d358a27b994861dc20b83cf98e (patch)
tree8bdb1509be601294329f9a6739823cc798ad9de1 /packages/taler-wallet-core/src/operations
parent80e43db2cac84e588c2ef3889e8d90b76bd53714 (diff)
downloadwallet-core-f5d194dfc61ae0d358a27b994861dc20b83cf98e.tar.gz
wallet-core-f5d194dfc61ae0d358a27b994861dc20b83cf98e.tar.bz2
wallet-core-f5d194dfc61ae0d358a27b994861dc20b83cf98e.zip
wallet: cancellation for deposit
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts40
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts60
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts4
3 files changed, 82 insertions, 22 deletions
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index 501e9b76b..c11c45dc6 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -21,6 +21,7 @@ import {
AbsoluteTime,
AmountJson,
Amounts,
+ CancellationToken,
canonicalJson,
codecForDepositSuccess,
ContractTerms,
@@ -125,23 +126,34 @@ async function reportDepositGroupError(
export async function processDepositGroup(
ws: InternalWalletState,
depositGroupId: string,
- forceNow = false,
+ options: {
+ forceNow?: boolean;
+ cancellationToken?: CancellationToken;
+ } = {},
): Promise<void> {
- await ws.memoProcessDeposit.memo(depositGroupId, async () => {
- const onOpErr = (err: TalerErrorDetail): Promise<void> =>
- reportDepositGroupError(ws, depositGroupId, err);
- return await guardOperationException(
- async () => await processDepositGroupImpl(ws, depositGroupId, forceNow),
- onOpErr,
- );
- });
+ if (ws.taskCancellationSourceForDeposit) {
+ ws.taskCancellationSourceForDeposit.cancel();
+ }
+ const onOpErr = (err: TalerErrorDetail): Promise<void> =>
+ reportDepositGroupError(ws, depositGroupId, err);
+ return await guardOperationException(
+ async () => await processDepositGroupImpl(ws, depositGroupId, options),
+ onOpErr,
+ );
}
+/**
+ * @see {processDepositGroup}
+ */
async function processDepositGroupImpl(
ws: InternalWalletState,
depositGroupId: string,
- forceNow = false,
+ options: {
+ forceNow?: boolean;
+ cancellationToken?: CancellationToken;
+ } = {},
): Promise<void> {
+ const forceNow = options.forceNow ?? false;
const depositGroup = await ws.db
.mktx((x) => ({
depositGroups: x.depositGroups,
@@ -170,6 +182,8 @@ async function processDepositGroupImpl(
"",
);
+ // Check for cancellation before expensive operations.
+ options.cancellationToken?.throwIfCancelled();
const depositPermissions = await generateDepositPermissions(
ws,
depositGroup.payCoinSelection,
@@ -196,9 +210,13 @@ async function processDepositGroupImpl(
denom_pub_hash: perm.h_denom,
merchant_pub: depositGroup.merchantPub,
};
+ // Check for cancellation before making network request.
+ options.cancellationToken?.throwIfCancelled();
const url = new URL(`coins/${perm.coin_pub}/deposit`, perm.exchange_url);
logger.info(`depositing to ${url}`);
- const httpResp = await ws.http.postJson(url.href, requestBody);
+ const httpResp = await ws.http.postJson(url.href, requestBody, {
+ cancellationToken: options.cancellationToken,
+ });
await readSuccessResponseJsonOrThrow(httpResp, codecForDepositSuccess());
await ws.db
.mktx((x) => ({ depositGroups: x.depositGroups }))
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 09449c875..fe1c9ef35 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -61,7 +61,11 @@ import {
readSuccessResponseTextOrThrow,
} from "../util/http.js";
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
-import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
+import {
+ initRetryInfo,
+ RetryInfo,
+ updateRetryInfoTimeout,
+} from "../util/retries.js";
import {
WALLET_CACHE_BREAKER_CLIENT_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION,
@@ -102,7 +106,7 @@ function denominationRecordFromKeys(
return d;
}
-async function handleExchangeUpdateError(
+async function reportExchangeUpdateError(
ws: InternalWalletState,
baseUrl: string,
err: TalerErrorDetail,
@@ -114,14 +118,44 @@ async function handleExchangeUpdateError(
if (!exchange) {
return;
}
- exchange.retryInfo.retryCounter++;
- updateRetryInfoTimeout(exchange.retryInfo);
exchange.lastError = err;
await tx.exchanges.put(exchange);
});
- if (err) {
- ws.notify({ type: NotificationType.ExchangeOperationError, error: err });
- }
+ ws.notify({ type: NotificationType.ExchangeOperationError, error: err });
+}
+
+async function resetExchangeUpdateRetry(
+ ws: InternalWalletState,
+ baseUrl: string,
+): Promise<void> {
+ await ws.db
+ .mktx((x) => ({ exchanges: x.exchanges }))
+ .runReadWrite(async (tx) => {
+ const exchange = await tx.exchanges.get(baseUrl);
+ if (!exchange) {
+ return;
+ }
+ delete exchange.lastError;
+ exchange.retryInfo = initRetryInfo();
+ await tx.exchanges.put(exchange);
+ });
+}
+
+async function incrementExchangeUpdateRetry(
+ ws: InternalWalletState,
+ baseUrl: string,
+): Promise<void> {
+ await ws.db
+ .mktx((x) => ({ exchanges: x.exchanges }))
+ .runReadWrite(async (tx) => {
+ const exchange = await tx.exchanges.get(baseUrl);
+ if (!exchange) {
+ return;
+ }
+ delete exchange.lastError;
+ exchange.retryInfo = RetryInfo.increment(exchange.retryInfo);
+ await tx.exchanges.put(exchange);
+ });
}
export function getExchangeRequestTimeout(): Duration {
@@ -349,7 +383,7 @@ export async function updateExchangeFromUrl(
exchangeDetails: ExchangeDetailsRecord;
}> {
const onOpErr = (e: TalerErrorDetail): Promise<void> =>
- handleExchangeUpdateError(ws, baseUrl, e);
+ reportExchangeUpdateError(ws, baseUrl, e);
return await guardOperationException(
() => updateExchangeFromUrlImpl(ws, baseUrl, acceptedFormat, forceNow),
onOpErr,
@@ -543,6 +577,12 @@ async function updateExchangeFromUrlImpl(
return { exchange, exchangeDetails };
}
+ if (forceNow) {
+ await resetExchangeUpdateRetry(ws, baseUrl);
+ } else {
+ await incrementExchangeUpdateRetry(ws, baseUrl);
+ }
+
logger.info("updating exchange /keys info");
const timeout = getExchangeRequestTimeout();
@@ -624,8 +664,8 @@ async function updateExchangeFromUrlImpl(
termsOfServiceAcceptedTimestamp: TalerProtocolTimestamp.now(),
};
// FIXME: only update if pointer got updated
- r.lastError = undefined;
- r.retryInfo = initRetryInfo();
+ delete r.lastError;
+ delete r.retryInfo;
r.lastUpdate = TalerProtocolTimestamp.now();
r.nextUpdate = keysInfo.expiry;
// New denominations might be available.
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index cb312154e..bb5306189 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -444,7 +444,9 @@ export async function retryTransaction(
switch (type) {
case TransactionType.Deposit:
const depositGroupId = rest[0];
- processDepositGroup(ws, depositGroupId, true);
+ processDepositGroup(ws, depositGroupId, {
+ forceNow: true,
+ });
break;
case TransactionType.Withdrawal:
const withdrawalGroupId = rest[0];