diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts | 123 |
1 files changed, 57 insertions, 66 deletions
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts index 427961f44..23976f11b 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts @@ -17,6 +17,7 @@ import { AcceptPeerPushPaymentResponse, Amounts, + CancellationToken, ConfirmPeerPushCreditRequest, ContractTermsUtil, ExchangePurseMergeRequest, @@ -54,9 +55,10 @@ import { InternalWalletState, KycPendingInfo, KycUserType, - PeerPushPaymentIncomingRecord, PeerPushCreditStatus, + PeerPushPaymentIncomingRecord, PendingTaskType, + TaskId, WithdrawalGroupStatus, WithdrawalRecordType, timestampPreciseToDb, @@ -69,9 +71,8 @@ import { TombstoneTag, TransactionContext, constructTaskIdentifier, - runLongpollAsync, } from "./common.js"; -import { fetchFreshExchange, markExchangeUsed } from "./exchanges.js"; +import { fetchFreshExchange } from "./exchanges.js"; import { codecForExchangePurseStatus, getMergeReserveInfo, @@ -81,7 +82,6 @@ import { constructTransactionIdentifier, notifyTransition, parseTransactionIdentifier, - stopLongpolling, } from "./transactions.js"; import { PerformCreateWithdrawalGroupResult, @@ -93,8 +93,8 @@ import { const logger = new Logger("pay-peer-push-credit.ts"); export class PeerPushCreditTransactionContext implements TransactionContext { - private transactionId: string; - private retryTag: string; + readonly transactionId: string; + readonly retryTag: TaskId; constructor( public ws: InternalWalletState, @@ -141,7 +141,6 @@ export class PeerPushCreditTransactionContext implements TransactionContext { async suspendTransaction(): Promise<void> { const { ws, peerPushCreditId, retryTag, transactionId } = this; - stopLongpolling(ws, retryTag); const transitionInfo = await ws.db.runReadWriteTx( ["peerPushCredit"], async (tx) => { @@ -191,11 +190,11 @@ export class PeerPushCreditTransactionContext implements TransactionContext { }, ); notifyTransition(ws, transactionId, transitionInfo); + ws.taskScheduler.stopShepherdTask(retryTag); } async abortTransaction(): Promise<void> { const { ws, peerPushCreditId, retryTag, transactionId } = this; - stopLongpolling(ws, retryTag); const transitionInfo = await ws.db.runReadWriteTx( ["peerPushCredit"], async (tx) => { @@ -248,11 +247,11 @@ export class PeerPushCreditTransactionContext implements TransactionContext { }, ); notifyTransition(ws, transactionId, transitionInfo); + ws.taskScheduler.startShepherdTask(retryTag); } async resumeTransaction(): Promise<void> { const { ws, peerPushCreditId, retryTag, transactionId } = this; - stopLongpolling(ws, retryTag); const transitionInfo = await ws.db.runReadWriteTx( ["peerPushCredit"], async (tx) => { @@ -300,13 +299,12 @@ export class PeerPushCreditTransactionContext implements TransactionContext { return undefined; }, ); - ws.workAvailable.trigger(); notifyTransition(ws, transactionId, transitionInfo); + ws.taskScheduler.startShepherdTask(retryTag); } async failTransaction(): Promise<void> { const { ws, peerPushCreditId, retryTag, transactionId } = this; - stopLongpolling(ws, retryTag); const transitionInfo = await ws.db.runReadWriteTx( ["peerPushCredit"], async (tx) => { @@ -349,8 +347,9 @@ export class PeerPushCreditTransactionContext implements TransactionContext { return undefined; }, ); - ws.workAvailable.trigger(); + ws.taskScheduler.stopShepherdTask(retryTag); notifyTransition(ws, transactionId, transitionInfo); + ws.taskScheduler.startShepherdTask(retryTag); } } @@ -521,63 +520,51 @@ async function longpollKycStatus( exchangeUrl: string, kycInfo: KycPendingInfo, userType: KycUserType, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const transactionId = constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, peerPushCreditId, }); - const retryTag = constructTaskIdentifier({ - tag: PendingTaskType.PeerPushCredit, - peerPushCreditId, - }); - - runLongpollAsync(ws, retryTag, async (ct) => { - const url = new URL( - `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, - exchangeUrl, - ); - url.searchParams.set("timeout_ms", "10000"); - logger.info(`kyc url ${url.href}`); - const kycStatusRes = await ws.http.fetch(url.href, { - method: "GET", - cancellationToken: ct, - }); - if ( - kycStatusRes.status === HttpStatusCode.Ok || - //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge - // remove after the exchange is fixed or clarified - kycStatusRes.status === HttpStatusCode.NoContent - ) { - const transitionInfo = await ws.db - .mktx((x) => [x.peerPushCredit]) - .runReadWrite(async (tx) => { - const peerInc = await tx.peerPushCredit.get(peerPushCreditId); - if (!peerInc) { - return; - } - if (peerInc.status !== PeerPushCreditStatus.PendingMergeKycRequired) { - return; - } - const oldTxState = computePeerPushCreditTransactionState(peerInc); - peerInc.status = PeerPushCreditStatus.PendingMerge; - const newTxState = computePeerPushCreditTransactionState(peerInc); - await tx.peerPushCredit.put(peerInc); - return { oldTxState, newTxState }; - }); - notifyTransition(ws, transactionId, transitionInfo); - return { ready: true }; - } else if (kycStatusRes.status === HttpStatusCode.Accepted) { - // FIXME: Do we have to update the URL here? - return { ready: false }; - } else { - throw Error( - `unexpected response from kyc-check (${kycStatusRes.status})`, - ); - } + const url = new URL( + `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, + exchangeUrl, + ); + url.searchParams.set("timeout_ms", "10000"); + logger.info(`kyc url ${url.href}`); + const kycStatusRes = await ws.http.fetch(url.href, { + method: "GET", + cancellationToken, }); - return { - type: TaskRunResultType.Longpoll, - }; + if ( + kycStatusRes.status === HttpStatusCode.Ok || + //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge + // remove after the exchange is fixed or clarified + kycStatusRes.status === HttpStatusCode.NoContent + ) { + const transitionInfo = await ws.db + .mktx((x) => [x.peerPushCredit]) + .runReadWrite(async (tx) => { + const peerInc = await tx.peerPushCredit.get(peerPushCreditId); + if (!peerInc) { + return; + } + if (peerInc.status !== PeerPushCreditStatus.PendingMergeKycRequired) { + return; + } + const oldTxState = computePeerPushCreditTransactionState(peerInc); + peerInc.status = PeerPushCreditStatus.PendingMerge; + const newTxState = computePeerPushCreditTransactionState(peerInc); + await tx.peerPushCredit.put(peerInc); + return { oldTxState, newTxState }; + }); + notifyTransition(ws, transactionId, transitionInfo); + } else if (kycStatusRes.status === HttpStatusCode.Accepted) { + // FIXME: Do we have to update the URL here? + } else { + throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`); + } + return TaskRunResult.backoff(); } async function processPeerPushCreditKycRequired( @@ -786,7 +773,7 @@ async function handlePendingMerge( ); notifyTransition(ws, transactionId, txRes?.peerPushCreditTransition); - return TaskRunResult.finished(); + return TaskRunResult.backoff(); } async function handlePendingWithdrawing( @@ -839,13 +826,14 @@ async function handlePendingWithdrawing( return TaskRunResult.finished(); } else { // FIXME: Return indicator that we depend on the other operation! - return TaskRunResult.pending(); + return TaskRunResult.backoff(); } } export async function processPeerPushCredit( ws: InternalWalletState, peerPushCreditId: string, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { let peerInc: PeerPushPaymentIncomingRecord | undefined; let contractTerms: PeerContractTerms | undefined; @@ -886,6 +874,7 @@ export async function processPeerPushCredit( peerInc.exchangeBaseUrl, peerInc.kycInfo, "individual", + cancellationToken, ); } @@ -940,7 +929,9 @@ export async function confirmPeerPushCredit( ); } - ws.workAvailable.trigger(); + const ctx = new PeerPushCreditTransactionContext(ws, peerPushCreditId); + + ws.taskScheduler.startShepherdTask(ctx.retryTag); const transactionId = constructTransactionIdentifier({ tag: TransactionType.PeerPushCredit, |