summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-03-28 23:21:49 +0200
committerFlorian Dold <florian@dold.me>2022-03-28 23:21:49 +0200
commit80e43db2cac84e588c2ef3889e8d90b76bd53714 (patch)
tree04297a4ad1838f9c1add039d64ee1b1996cfd6b2 /packages/taler-wallet-core
parentc194bd539a9e01d083b953ef1e0022da90574339 (diff)
downloadwallet-core-80e43db2cac84e588c2ef3889e8d90b76bd53714.tar.gz
wallet-core-80e43db2cac84e588c2ef3889e8d90b76bd53714.tar.bz2
wallet-core-80e43db2cac84e588c2ef3889e8d90b76bd53714.zip
wallet: timeout handling refactoring WIP
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/operations/common.ts3
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts129
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts26
-rw-r--r--packages/taler-wallet-core/src/operations/pay.ts7
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts33
-rw-r--r--packages/taler-wallet-core/src/util/retries.ts15
-rw-r--r--packages/taler-wallet-core/src/wallet.ts5
7 files changed, 109 insertions, 109 deletions
diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts
index 5261b114d..0fdde9dca 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -14,6 +14,9 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+/**
+ * Imports.
+ */
import { TalerErrorDetail, TalerErrorCode } from "@gnu-taler/taler-util";
import { CryptoApiStoppedError } from "../crypto/workers/cryptoDispatcher.js";
import { TalerError, getErrorDetailFromException } from "../errors.js";
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index 2e14afdf1..501e9b76b 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -14,17 +14,15 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+/**
+ * Imports.
+ */
import {
AbsoluteTime,
AmountJson,
Amounts,
- buildCodecForObject,
canonicalJson,
- Codec,
codecForDepositSuccess,
- codecForString,
- codecForTimestamp,
- codecOptional,
ContractTerms,
CreateDepositGroupRequest,
CreateDepositGroupResponse,
@@ -42,21 +40,22 @@ import {
TrackDepositGroupResponse,
URL,
} from "@gnu-taler/taler-util";
-import { InternalWalletState } from "../internal-wallet-state.js";
import { DepositGroupRecord, OperationStatus } from "../db.js";
+import { InternalWalletState } from "../internal-wallet-state.js";
import { PayCoinSelection, selectPayCoins } from "../util/coinSelection.js";
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
-import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
+import { initRetryInfo, RetryInfo } from "../util/retries.js";
+import { guardOperationException } from "./common.js";
import { getExchangeDetails } from "./exchanges.js";
import {
applyCoinSpend,
+ CoinSelectionRequest,
extractContractData,
generateDepositPermissions,
getCandidatePayCoins,
getTotalPaymentCost,
} from "./pay.js";
import { getTotalRefreshCost } from "./refresh.js";
-import { guardOperationException } from "./common.js";
/**
* Logger.
@@ -73,17 +72,36 @@ async function resetDepositGroupRetry(
}))
.runReadWrite(async (tx) => {
const x = await tx.depositGroups.get(depositGroupId);
- if (x) {
- x.retryInfo = initRetryInfo();
- await tx.depositGroups.put(x);
+ if (!x) {
+ return;
+ }
+ x.retryInfo = initRetryInfo();
+ delete x.lastError;
+ await tx.depositGroups.put(x);
+ });
+}
+
+async function incrementDepositGroupRetry(
+ ws: InternalWalletState,
+ depositGroupId: string,
+): Promise<void> {
+ await ws.db
+ .mktx((x) => ({ depositGroups: x.depositGroups }))
+ .runReadWrite(async (tx) => {
+ const r = await tx.depositGroups.get(depositGroupId);
+ if (!r) {
+ return;
}
+ r.retryInfo = RetryInfo.increment(r.retryInfo);
+ delete r.lastError;
+ await tx.depositGroups.put(r);
});
}
-async function incrementDepositRetry(
+async function reportDepositGroupError(
ws: InternalWalletState,
depositGroupId: string,
- err: TalerErrorDetail | undefined,
+ err: TalerErrorDetail,
): Promise<void> {
await ws.db
.mktx((x) => ({ depositGroups: x.depositGroups }))
@@ -93,16 +111,15 @@ async function incrementDepositRetry(
return;
}
if (!r.retryInfo) {
+ logger.error(
+ `deposit group record (${depositGroupId}) reports error, but no retry active`,
+ );
return;
}
- r.retryInfo.retryCounter++;
- updateRetryInfoTimeout(r.retryInfo);
r.lastError = err;
await tx.depositGroups.put(r);
});
- if (err) {
- ws.notify({ type: NotificationType.DepositOperationError, error: err });
- }
+ ws.notify({ type: NotificationType.DepositOperationError, error: err });
}
export async function processDepositGroup(
@@ -111,8 +128,8 @@ export async function processDepositGroup(
forceNow = false,
): Promise<void> {
await ws.memoProcessDeposit.memo(depositGroupId, async () => {
- const onOpErr = (e: TalerErrorDetail): Promise<void> =>
- incrementDepositRetry(ws, depositGroupId, e);
+ const onOpErr = (err: TalerErrorDetail): Promise<void> =>
+ reportDepositGroupError(ws, depositGroupId, err);
return await guardOperationException(
async () => await processDepositGroupImpl(ws, depositGroupId, forceNow),
onOpErr,
@@ -125,9 +142,6 @@ async function processDepositGroupImpl(
depositGroupId: string,
forceNow = false,
): Promise<void> {
- if (forceNow) {
- await resetDepositGroupRetry(ws, depositGroupId);
- }
const depositGroup = await ws.db
.mktx((x) => ({
depositGroups: x.depositGroups,
@@ -144,6 +158,12 @@ async function processDepositGroupImpl(
return;
}
+ if (forceNow) {
+ await resetDepositGroupRetry(ws, depositGroupId);
+ } else {
+ await incrementDepositGroupRetry(ws, depositGroupId);
+ }
+
const contractData = extractContractData(
depositGroup.contractTermsRaw,
depositGroup.contractTermsHash,
@@ -306,42 +326,25 @@ export async function getFeeForDeposit(
}
});
- const timestamp = AbsoluteTime.now();
- const timestampRound = AbsoluteTime.toTimestamp(timestamp);
- const contractTerms: ContractTerms = {
- auditors: [],
- exchanges: exchangeInfos,
- amount: req.amount,
- max_fee: Amounts.stringify(amount),
- max_wire_fee: Amounts.stringify(amount),
- wire_method: p.targetType,
- timestamp: timestampRound,
- merchant_base_url: "",
- summary: "",
- nonce: "",
- wire_transfer_deadline: timestampRound,
- order_id: "",
- h_wire: "",
- pay_deadline: AbsoluteTime.toTimestamp(
- AbsoluteTime.addDuration(timestamp, durationFromSpec({ hours: 1 })),
- ),
- merchant: {
- name: "",
- },
- merchant_pub: "",
- refund_deadline: TalerProtocolTimestamp.zero(),
+ const csr: CoinSelectionRequest = {
+ allowedAuditors: [],
+ allowedExchanges: [],
+ amount: Amounts.parseOrThrow(req.amount),
+ maxDepositFee: Amounts.parseOrThrow(req.amount),
+ maxWireFee: Amounts.parseOrThrow(req.amount),
+ timestamp: TalerProtocolTimestamp.now(),
+ wireFeeAmortization: 1,
+ wireMethod: p.targetType,
};
- const contractData = extractContractData(contractTerms, "", "");
-
- const candidates = await getCandidatePayCoins(ws, contractData);
+ const candidates = await getCandidatePayCoins(ws, csr);
const payCoinSel = selectPayCoins({
candidates,
- contractTermsAmount: contractData.amount,
- depositFeeLimit: contractData.maxDepositFee,
- wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
- wireFeeLimit: contractData.maxWireFee,
+ contractTermsAmount: csr.amount,
+ depositFeeLimit: csr.maxDepositFee,
+ wireFeeAmortization: csr.wireFeeAmortization,
+ wireFeeLimit: csr.maxWireFee,
prevPayCoins: [],
});
@@ -573,6 +576,7 @@ export async function getEffectiveDepositAmount(
return Amounts.sub(Amounts.sum(amt).amount, Amounts.sum(fees).amount).amount;
}
+// FIXME: rename to DepositGroupFee
export interface DepositFee {
coin: AmountJson;
wire: AmountJson;
@@ -594,8 +598,6 @@ export async function getTotalFeeForDepositAmount(
const refreshFee: AmountJson[] = [];
const exchangeSet: Set<string> = new Set();
- // let acc: AmountJson = Amounts.getZero(total.currency);
-
await ws.db
.mktx((x) => ({
coins: x.coins,
@@ -658,17 +660,8 @@ export async function getTotalFeeForDepositAmount(
});
return {
- coin:
- coinFee.length === 0
- ? Amounts.getZero(total.currency)
- : Amounts.sum(coinFee).amount,
- wire:
- wireFee.length === 0
- ? Amounts.getZero(total.currency)
- : Amounts.sum(wireFee).amount,
- refresh:
- refreshFee.length === 0
- ? Amounts.getZero(total.currency)
- : Amounts.sum(refreshFee).amount,
+ coin: Amounts.sumOrZero(total.currency, coinFee).amount,
+ wire: Amounts.sumOrZero(total.currency, wireFee).amount,
+ refresh: Amounts.sumOrZero(total.currency, refreshFee).amount,
};
}
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 51b5c7806..09449c875 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -18,35 +18,31 @@
* Imports.
*/
import {
+ AbsoluteTime,
Amounts,
- ExchangeAuditor,
canonicalizeBaseUrl,
codecForExchangeKeysJson,
codecForExchangeWireJson,
- ExchangeDenomination,
+ DenominationPubKey,
Duration,
durationFromSpec,
+ encodeCrock,
+ ExchangeAuditor,
+ ExchangeDenomination,
ExchangeSignKeyJson,
ExchangeWireJson,
+ hashDenomPub,
+ LibtoolVersion,
Logger,
NotificationType,
parsePaytoUri,
Recoup,
TalerErrorCode,
- URL,
TalerErrorDetail,
- AbsoluteTime,
- hashDenomPub,
- LibtoolVersion,
- codecForAny,
- DenominationPubKey,
- DenomKeyType,
- ExchangeKeysJson,
- TalerProtocolTimestamp,
TalerProtocolDuration,
+ TalerProtocolTimestamp,
+ URL,
} from "@gnu-taler/taler-util";
-import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util";
-import { CryptoDispatcher } from "../crypto/workers/cryptoDispatcher.js";
import {
DenominationRecord,
DenominationVerificationStatus,
@@ -56,6 +52,8 @@ import {
WireFee,
WireInfo,
} from "../db.js";
+import { TalerError } from "../errors.js";
+import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
import {
getExpiry,
HttpRequestLibrary,
@@ -64,8 +62,6 @@ import {
} from "../util/http.js";
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
-import { TalerError } from "../errors.js";
-import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
import {
WALLET_CACHE_BREAKER_CLIENT_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION,
diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts
index 193ce54e2..b761367fb 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -98,6 +98,7 @@ import { GetReadWriteAccess } from "../util/query.js";
import {
getRetryDuration,
initRetryInfo,
+ RetryInfo,
updateRetryInfoTimeout,
} from "../util/retries.js";
import { getExchangeDetails } from "./exchanges.js";
@@ -539,11 +540,7 @@ async function incrementPurchasePayRetry(
if (!pr) {
return;
}
- if (!pr.payRetryInfo) {
- pr.payRetryInfo = initRetryInfo();
- }
- pr.payRetryInfo.retryCounter++;
- updateRetryInfoTimeout(pr.payRetryInfo);
+ pr.payRetryInfo = RetryInfo.increment(pr.payRetryInfo);
delete pr.lastPayError;
await tx.purchases.put(pr);
});
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 7997ab5be..4a7adbb9c 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -18,32 +18,31 @@
* Imports.
*/
import {
+ AbsoluteTime,
AmountJson,
Amounts,
+ AmountString,
BankWithdrawDetails,
codecForTalerConfigResponse,
codecForWithdrawOperationStatusResponse,
codecForWithdrawResponse,
+ DenomKeyType,
+ Duration,
durationFromSpec,
ExchangeListItem,
+ ExchangeWithdrawRequest,
+ LibtoolVersion,
Logger,
NotificationType,
parseWithdrawUri,
TalerErrorCode,
TalerErrorDetail,
- AbsoluteTime,
- WithdrawResponse,
+ TalerProtocolTimestamp,
+ UnblindedSignature,
URL,
- WithdrawUriInfoResponse,
VersionMatchResult,
- DenomKeyType,
- LibtoolVersion,
- UnblindedSignature,
- ExchangeWithdrawRequest,
- Duration,
- TalerProtocolTimestamp,
- TransactionType,
- AmountString,
+ WithdrawResponse,
+ WithdrawUriInfoResponse,
} from "@gnu-taler/taler-util";
import {
CoinRecord,
@@ -58,18 +57,18 @@ import {
PlanchetRecord,
WithdrawalGroupRecord,
} from "../db.js";
-import { walletCoreDebugFlags } from "../util/debugFlags.js";
-import {
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
-} from "../util/http.js";
-import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
import {
getErrorDetailFromException,
makeErrorDetail,
TalerError,
} from "../errors.js";
import { InternalWalletState } from "../internal-wallet-state.js";
+import { walletCoreDebugFlags } from "../util/debugFlags.js";
+import {
+ HttpRequestLibrary,
+ readSuccessResponseJsonOrThrow,
+} from "../util/http.js";
+import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js";
import {
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
WALLET_EXCHANGE_PROTOCOL_VERSION,
diff --git a/packages/taler-wallet-core/src/util/retries.ts b/packages/taler-wallet-core/src/util/retries.ts
index 4b78d38ef..25b4c5055 100644
--- a/packages/taler-wallet-core/src/util/retries.ts
+++ b/packages/taler-wallet-core/src/util/retries.ts
@@ -92,3 +92,18 @@ export function initRetryInfo(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
updateRetryInfoTimeout(info, p);
return info;
}
+
+export namespace RetryInfo {
+ export function increment(
+ r: RetryInfo | undefined,
+ p: RetryPolicy = defaultRetryPolicy,
+ ) {
+ if (!r) {
+ return initRetryInfo(p);
+ }
+ const r2 = { ...r };
+ r2.retryCounter++;
+ updateRetryInfoTimeout(r2, p);
+ return r2;
+ }
+}
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index bb560774a..943051153 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -193,10 +193,7 @@ import {
import { DbAccess, GetReadWriteAccess } from "./util/query.js";
import { TimerGroup } from "./util/timer.js";
import { WalletCoreApiClient } from "./wallet-api-types.js";
-import {
- TalerCryptoInterface,
- TalerCryptoInterfaceR,
-} from "./crypto/cryptoImplementation.js";
+import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
const builtinAuditors: AuditorTrustRecord[] = [
{