diff options
author | Florian Dold <florian@dold.me> | 2022-03-29 13:47:32 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2022-03-29 13:48:51 +0200 |
commit | c265e7d019d445add2d2cfb7cfcbdeee059684d3 (patch) | |
tree | 6904e9cdb723992728ed511103be65094ca50034 /packages/taler-wallet-core/src/operations/tip.ts | |
parent | be489b6b3ea4214f546dfc33d6bb0f39ce82b5ab (diff) | |
download | wallet-core-c265e7d019d445add2d2cfb7cfcbdeee059684d3.tar.xz |
wallet: make retries more robust and consistent
Diffstat (limited to 'packages/taler-wallet-core/src/operations/tip.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/tip.ts | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 9582f18e8..8bf85fe99 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -43,7 +43,11 @@ import { } from "../db.js"; import { j2s } from "@gnu-taler/taler-util"; import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js"; -import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries.js"; +import { + resetRetryInfo, + RetryInfo, + updateRetryInfoTimeout, +} from "../util/retries.js"; import { makeErrorDetail } from "../errors.js"; import { updateExchangeFromUrl } from "./exchanges.js"; import { InternalWalletState } from "../internal-wallet-state.js"; @@ -127,7 +131,7 @@ export async function prepareTip( createdTimestamp: TalerProtocolTimestamp.now(), merchantTipId: res.merchantTipId, tipAmountEffective: selectedDenoms.totalCoinValue, - retryInfo: initRetryInfo(), + retryInfo: resetRetryInfo(), lastError: undefined, denomsSel: denomSelectionInfoToState(selectedDenoms), pickedUpTimestamp: undefined, @@ -157,10 +161,10 @@ export async function prepareTip( return tipStatus; } -async function incrementTipRetry( +async function reportTipError( ws: InternalWalletState, walletTipId: string, - err: TalerErrorDetail | undefined, + err: TalerErrorDetail, ): Promise<void> { await ws.db .mktx((x) => ({ @@ -172,10 +176,8 @@ async function incrementTipRetry( return; } if (!t.retryInfo) { - return; + logger.reportBreak(); } - t.retryInfo.retryCounter++; - updateRetryInfoTimeout(t.retryInfo); t.lastError = err; await tx.tips.put(t); }); @@ -184,15 +186,43 @@ async function incrementTipRetry( } } +async function setupTipRetry( + ws: InternalWalletState, + walletTipId: string, + options: { + reset: boolean; + }, +): Promise<void> { + await ws.db + .mktx((x) => ({ + tips: x.tips, + })) + .runReadWrite(async (tx) => { + const t = await tx.tips.get(walletTipId); + if (!t) { + return; + } + if (options.reset) { + t.retryInfo = resetRetryInfo(); + } else { + t.retryInfo = RetryInfo.increment(t.retryInfo); + } + delete t.lastError; + await tx.tips.put(t); + }); +} + export async function processTip( ws: InternalWalletState, tipId: string, - forceNow = false, + options: { + forceNow?: boolean; + } = {}, ): Promise<void> { const onOpErr = (e: TalerErrorDetail): Promise<void> => - incrementTipRetry(ws, tipId, e); + reportTipError(ws, tipId, e); await guardOperationException( - () => processTipImpl(ws, tipId, forceNow), + () => processTipImpl(ws, tipId, options), onOpErr, ); } @@ -208,7 +238,7 @@ async function resetTipRetry( .runReadWrite(async (tx) => { const x = await tx.tips.get(tipId); if (x) { - x.retryInfo = initRetryInfo(); + x.retryInfo = resetRetryInfo(); await tx.tips.put(x); } }); @@ -217,8 +247,11 @@ async function resetTipRetry( async function processTipImpl( ws: InternalWalletState, walletTipId: string, - forceNow: boolean, + options: { + forceNow?: boolean; + } = {}, ): Promise<void> { + const forceNow = options.forceNow ?? false; if (forceNow) { await resetTipRetry(ws, walletTipId); } @@ -293,12 +326,13 @@ async function processTipImpl( merchantResp.status === 424) ) { logger.trace(`got transient tip error`); + // FIXME: wrap in another error code that indicates a transient error const err = makeErrorDetail( TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR, getHttpResponseErrorDetails(merchantResp), "tip pickup failed (transient)", ); - await incrementTipRetry(ws, tipRecord.walletTipId, err); + await reportTipError(ws, tipRecord.walletTipId, err); // FIXME: Maybe we want to signal to the caller that the transient error happened? return; } @@ -397,7 +431,7 @@ async function processTipImpl( } tr.pickedUpTimestamp = TalerProtocolTimestamp.now(); tr.lastError = undefined; - tr.retryInfo = initRetryInfo(); + tr.retryInfo = resetRetryInfo(); await tx.tips.put(tr); for (const cr of newCoinRecords) { await tx.coins.put(cr); |