wallet-core: implement cancelAbortingTransaction for deposit groups
This commit is contained in:
parent
8624d798b7
commit
fe8749c3f8
@ -1713,6 +1713,16 @@ export const codecForAcceptTipRequest = (): Codec<AcceptTipRequest> =>
|
||||
.property("walletTipId", codecForString())
|
||||
.build("AcceptTipRequest");
|
||||
|
||||
export interface CancelAbortingTransactionRequest {
|
||||
transactionId: TransactionIdStr;
|
||||
}
|
||||
|
||||
export const codecForCancelAbortingTransactionRequest =
|
||||
(): Codec<CancelAbortingTransactionRequest> =>
|
||||
buildCodecForObject<CancelAbortingTransactionRequest>()
|
||||
.property("transactionId", codecForTransactionIdStr())
|
||||
.build("CancelAbortingTransactionRequest");
|
||||
|
||||
export interface SuspendTransactionRequest {
|
||||
transactionId: TransactionIdStr;
|
||||
}
|
||||
|
@ -1628,11 +1628,15 @@ export interface BackupProviderRecord {
|
||||
}
|
||||
|
||||
export enum DepositOperationStatus {
|
||||
Finished = 50 /* OperationStatusRange.DORMANT_START */,
|
||||
Suspended = 51 /* OperationStatusRange.DORMANT_START + 1 */,
|
||||
Aborted = 52 /* OperationStatusRange.DORMANT_START + 2 */,
|
||||
Pending = 10 /* OperationStatusRange.ACTIVE_START */,
|
||||
Aborting = 11 /* OperationStatusRange.ACTIVE_START + 1 */,
|
||||
Pending = 10,
|
||||
Aborting = 11,
|
||||
|
||||
Suspended = 20,
|
||||
SuspendedAborting = 21,
|
||||
|
||||
Finished = 50,
|
||||
Failed = 51,
|
||||
Aborted = 52,
|
||||
}
|
||||
|
||||
export interface DepositTrackingInfo {
|
||||
|
@ -167,6 +167,14 @@ export function computeDepositTransactionStatus(
|
||||
return {
|
||||
major: TransactionMajorState.Aborted,
|
||||
}
|
||||
case DepositOperationStatus.Failed:
|
||||
return {
|
||||
major: TransactionMajorState.Failed,
|
||||
}
|
||||
case DepositOperationStatus.SuspendedAborting:
|
||||
return {
|
||||
major: TransactionMajorState.SuspendedAborting,
|
||||
}
|
||||
default:
|
||||
throw Error(`unexpected deposit group state (${dg.operationStatus})`);
|
||||
}
|
||||
@ -184,7 +192,7 @@ export async function suspendDepositGroup(
|
||||
tag: PendingTaskType.Deposit,
|
||||
depositGroupId,
|
||||
});
|
||||
let res = await ws.db
|
||||
const transitionInfo = await ws.db
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
@ -212,14 +220,7 @@ export async function suspendDepositGroup(
|
||||
return undefined;
|
||||
});
|
||||
stopLongpolling(ws, retryTag);
|
||||
if (res) {
|
||||
ws.notify({
|
||||
type: NotificationType.TransactionStateTransition,
|
||||
transactionId,
|
||||
oldTxState: res.oldTxState,
|
||||
newTxState: res.newTxState,
|
||||
});
|
||||
}
|
||||
notifyTransition(ws, transactionId, transitionInfo);
|
||||
}
|
||||
|
||||
export async function resumeDepositGroup(
|
||||
@ -230,7 +231,7 @@ export async function resumeDepositGroup(
|
||||
tag: TransactionType.Deposit,
|
||||
depositGroupId,
|
||||
});
|
||||
let res = await ws.db
|
||||
const transitionInfo = await ws.db
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
@ -258,14 +259,7 @@ export async function resumeDepositGroup(
|
||||
return undefined;
|
||||
});
|
||||
ws.workAvailable.trigger();
|
||||
if (res) {
|
||||
ws.notify({
|
||||
type: NotificationType.TransactionStateTransition,
|
||||
transactionId,
|
||||
oldTxState: res.oldTxState,
|
||||
newTxState: res.newTxState,
|
||||
});
|
||||
}
|
||||
notifyTransition(ws, transactionId, transitionInfo);
|
||||
}
|
||||
|
||||
export async function abortDepositGroup(
|
||||
@ -280,7 +274,7 @@ export async function abortDepositGroup(
|
||||
tag: PendingTaskType.Deposit,
|
||||
depositGroupId,
|
||||
});
|
||||
let res = await ws.db
|
||||
const transitionInfo = await ws.db
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
@ -311,14 +305,48 @@ export async function abortDepositGroup(
|
||||
stopLongpolling(ws, retryTag);
|
||||
// Need to process the operation again.
|
||||
ws.workAvailable.trigger();
|
||||
if (res) {
|
||||
ws.notify({
|
||||
type: NotificationType.TransactionStateTransition,
|
||||
transactionId,
|
||||
oldTxState: res.oldTxState,
|
||||
newTxState: res.newTxState,
|
||||
});
|
||||
notifyTransition(ws, transactionId, transitionInfo);
|
||||
}
|
||||
|
||||
export async function cancelAbortingDepositGroup(
|
||||
ws: InternalWalletState,
|
||||
depositGroupId: string,
|
||||
): Promise<void> {
|
||||
const transactionId = constructTransactionIdentifier({
|
||||
tag: TransactionType.Deposit,
|
||||
depositGroupId,
|
||||
});
|
||||
const retryTag = constructTaskIdentifier({
|
||||
tag: PendingTaskType.Deposit,
|
||||
depositGroupId,
|
||||
});
|
||||
const transitionInfo = await ws.db
|
||||
.mktx((x) => [x.depositGroups])
|
||||
.runReadWrite(async (tx) => {
|
||||
const dg = await tx.depositGroups.get(depositGroupId);
|
||||
if (!dg) {
|
||||
logger.warn(
|
||||
`can't cancel aborting deposit group, depositGroupId=${depositGroupId} not found`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
const oldState = computeDepositTransactionStatus(dg);
|
||||
switch (dg.operationStatus) {
|
||||
case DepositOperationStatus.SuspendedAborting:
|
||||
case DepositOperationStatus.Aborting: {
|
||||
dg.operationStatus = DepositOperationStatus.Failed;
|
||||
await tx.depositGroups.put(dg);
|
||||
return {
|
||||
oldTxState: oldState,
|
||||
newTxState: computeDepositTransactionStatus(dg),
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
// FIXME: Also cancel ongoing work (via cancellation token, once implemented)
|
||||
stopLongpolling(ws, retryTag);
|
||||
notifyTransition(ws, transactionId, transitionInfo);
|
||||
}
|
||||
|
||||
export async function deleteDepositGroup(
|
||||
|
@ -75,6 +75,7 @@ import {
|
||||
} from "./common.js";
|
||||
import {
|
||||
abortDepositGroup,
|
||||
cancelAbortingDepositGroup,
|
||||
computeDepositTransactionStatus,
|
||||
processDepositGroup,
|
||||
resumeDepositGroup,
|
||||
@ -1401,6 +1402,23 @@ export async function suspendTransaction(
|
||||
}
|
||||
}
|
||||
|
||||
export async function cancelAbortingTransaction(
|
||||
ws: InternalWalletState,
|
||||
transactionId: string,
|
||||
): Promise<void> {
|
||||
const tx = parseTransactionIdentifier(transactionId);
|
||||
if (!tx) {
|
||||
throw Error("invalid transaction ID");
|
||||
}
|
||||
switch (tx.tag) {
|
||||
case TransactionType.Deposit:
|
||||
await cancelAbortingDepositGroup(ws, tx.depositGroupId);
|
||||
return;
|
||||
default:
|
||||
logger.warn(`unable to suspend transaction of type '${tx.tag}'`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume a suspended transaction.
|
||||
*/
|
||||
|
@ -65,6 +65,7 @@ import {
|
||||
codecForApplyDevExperiment,
|
||||
codecForApplyRefundFromPurchaseIdRequest,
|
||||
codecForApplyRefundRequest,
|
||||
codecForCancelAbortingTransactionRequest,
|
||||
codecForCheckPeerPullPaymentRequest,
|
||||
codecForCheckPeerPushDebitRequest,
|
||||
codecForConfirmPayRequest,
|
||||
@ -231,6 +232,7 @@ import {
|
||||
import { acceptTip, prepareTip, processTip } from "./operations/tip.js";
|
||||
import {
|
||||
abortTransaction,
|
||||
cancelAbortingTransaction,
|
||||
deleteTransaction,
|
||||
getTransactionById,
|
||||
getTransactions,
|
||||
@ -1229,6 +1231,11 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
|
||||
await suspendTransaction(ws, req.transactionId);
|
||||
return {};
|
||||
}
|
||||
case WalletApiOperation.CancelAbortingTransaction: {
|
||||
const req = codecForCancelAbortingTransactionRequest().decode(payload);
|
||||
await cancelAbortingTransaction(ws, req.transactionId);
|
||||
return {};
|
||||
}
|
||||
case WalletApiOperation.ResumeTransaction: {
|
||||
const req = codecForResumeTransaction().decode(payload);
|
||||
await resumeTransaction(ws, req.transactionId);
|
||||
|
Loading…
Reference in New Issue
Block a user