summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-07-01 01:43:29 +0200
committerFlorian Dold <florian@dold.me>2023-07-01 01:43:29 +0200
commit5695ae0a9f469ddbcd86e675f8f74b30032be457 (patch)
treedaf5f7de0d9c3549ac9acf6dde4189a2ddbe3ec9 /packages/taler-wallet-core
parentf93ab03a1b946af441e35b9c057f129d25311273 (diff)
downloadwallet-core-5695ae0a9f469ddbcd86e675f8f74b30032be457.tar.gz
wallet-core-5695ae0a9f469ddbcd86e675f8f74b30032be457.tar.bz2
wallet-core-5695ae0a9f469ddbcd86e675f8f74b30032be457.zip
wallet-core: use testingWaitTransactionsFinal to wait for transactions
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts28
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts14
-rw-r--r--packages/taler-wallet-core/src/wallet-api-types.ts11
-rw-r--r--packages/taler-wallet-core/src/wallet.ts3
4 files changed, 41 insertions, 15 deletions
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index fd6281eda..6eb221c1c 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -263,22 +263,25 @@ async function refreshCreateSession(
availableAmount,
)} too small`,
);
- // FIXME: State transition notification missing.
- await ws.db
+ const transitionInfo = await ws.db
.mktx((x) => [x.coins, x.coinAvailability, x.refreshGroups])
.runReadWrite(async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
if (!rg) {
return;
}
+ const oldTxState = computeRefreshTransactionState(rg);
rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished;
const updateRes = updateGroupStatus(rg);
if (updateRes.final) {
await makeCoinsVisible(ws, tx, transactionId);
}
await tx.refreshGroups.put(rg);
+ const newTxState = computeRefreshTransactionState(rg);
+ return { oldTxState, newTxState };
});
ws.notify({ type: NotificationType.BalanceChange });
+ notifyTransition(ws, transactionId, transitionInfo);
return;
}
@@ -438,7 +441,7 @@ async function refreshMelt(
if (resp.status === HttpStatusCode.NotFound) {
const errDetails = await readUnexpectedResponseDetails(resp);
- await ws.db
+ const transitionInfo = await ws.db
.mktx((x) => [x.refreshGroups, x.coins, x.coinAvailability])
.runReadWrite(async (tx) => {
const rg = await tx.refreshGroups.get(refreshGroupId);
@@ -451,6 +454,7 @@ async function refreshMelt(
if (rg.statusPerCoin[coinIndex] !== RefreshCoinStatus.Pending) {
return;
}
+ const oldTxState = computeRefreshTransactionState(rg);
rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Failed;
rg.lastErrorPerCoin[coinIndex] = errDetails;
const updateRes = updateGroupStatus(rg);
@@ -458,8 +462,14 @@ async function refreshMelt(
await makeCoinsVisible(ws, tx, transactionId);
}
await tx.refreshGroups.put(rg);
+ const newTxState = computeRefreshTransactionState(rg);
+ return {
+ oldTxState,
+ newTxState,
+ };
});
ws.notify({ type: NotificationType.BalanceChange });
+ notifyTransition(ws, transactionId, transitionInfo);
return;
}
@@ -739,7 +749,7 @@ async function refreshReveal(
}
}
- await ws.db
+ const transitionInfo = await ws.db
.mktx((x) => [
x.coins,
x.denominations,
@@ -756,6 +766,7 @@ async function refreshReveal(
if (!rs) {
return;
}
+ const oldTxState = computeRefreshTransactionState(rg);
rg.statusPerCoin[coinIndex] = RefreshCoinStatus.Finished;
updateGroupStatus(rg);
for (const coin of coins) {
@@ -763,7 +774,10 @@ async function refreshReveal(
}
await makeCoinsVisible(ws, tx, transactionId);
await tx.refreshGroups.put(rg);
+ const newTxState = computeRefreshTransactionState(rg);
+ return { oldTxState, newTxState };
});
+ notifyTransition(ws, transactionId, transitionInfo);
logger.trace("refresh finished (end of reveal)");
}
@@ -778,7 +792,7 @@ export async function processRefreshGroup(
.mktx((x) => [x.refreshGroups])
.runReadOnly(async (tx) => tx.refreshGroups.get(refreshGroupId));
if (!refreshGroup) {
- return TaskRunResult.finished()
+ return TaskRunResult.finished();
}
if (refreshGroup.timestampFinished) {
return TaskRunResult.finished();
@@ -1235,10 +1249,6 @@ export async function suspendRefreshGroup(
tag: TransactionType.Refresh,
refreshGroupId,
});
- const retryTag = constructTaskIdentifier({
- tag: PendingTaskType.Refresh,
- refreshGroupId,
- });
let res = await ws.db
.mktx((x) => [x.refreshGroups])
.runReadWrite(async (tx) => {
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index 8c84702b8..ea373e914 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -450,7 +450,7 @@ export async function runIntegrationTest(
logger.trace("integration test: all done!");
}
-async function waitUntilDone(ws: InternalWalletState): Promise<void> {
+export async function waitUntilDone(ws: InternalWalletState): Promise<void> {
logger.info("waiting until all transactions are in a final state");
ws.ensureTaskLoopRunning();
let p: OpenedPromise<void> | undefined = undefined;
@@ -459,11 +459,13 @@ async function waitUntilDone(ws: InternalWalletState): Promise<void> {
return;
}
if (notif.type === NotificationType.TransactionStateTransition) {
- p.resolve();
- }
- // Work-around, refresh transactions don't properly emit transition notifications yet.
- if (notif.type === NotificationType.PendingOperationProcessed) {
- p.resolve();
+ switch (notif.newTxState.major) {
+ case TransactionMajorState.Pending:
+ case TransactionMajorState.Aborting:
+ break;
+ default:
+ p.resolve();
+ }
}
});
while (1) {
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts
index 6bcee0299..cea548db6 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -206,6 +206,7 @@ export enum WalletApiOperation {
Recycle = "recycle",
ApplyDevExperiment = "applyDevExperiment",
ValidateIban = "validateIban",
+ TestingWaitTransactionsFinal = "testingWaitTransactionsFinal",
}
// group: Initialization
@@ -950,6 +951,15 @@ export type DumpCoinsOp = {
};
/**
+ * Wait until all transactions are in a final state.
+ */
+export type TestingWaitTransactionsFinal = {
+ op: WalletApiOperation.TestingWaitTransactionsFinal;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+
+/**
* Set a coin as (un-)suspended.
* Suspended coins won't be used for payments.
*/
@@ -1051,6 +1061,7 @@ export type WalletOperations = {
[WalletApiOperation.Recycle]: RecycleOp;
[WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp;
[WalletApiOperation.ValidateIban]: ValidateIbanOp;
+ [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinal;
};
export type WalletCoreRequestType<
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 8f11a3d28..11030af2b 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -242,6 +242,7 @@ import {
runIntegrationTest,
runIntegrationTest2,
testPay,
+ waitUntilDone,
withdrawTestBalance,
} from "./operations/testing.js";
import {
@@ -1550,6 +1551,8 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
case WalletApiOperation.GetVersion: {
return getVersion(ws);
}
+ case WalletApiOperation.TestingWaitTransactionsFinal:
+ return await waitUntilDone(ws);
// default:
// assertUnreachable(operation);
}