commit 71134277d046dad960d5d3223a45045bd0be49ac
parent df1e6cc2ad3203c7464ddc170ce3d7ff37b2821f
Author: Florian Dold <dold@taler.net>
Date: Sun, 19 Jul 2026 01:37:03 +0200
db: move transaction re-materialization behind the DAL
Diffstat:
6 files changed, 58 insertions(+), 39 deletions(-)
diff --git a/packages/taler-wallet-core/src/dbtx-indexeddb.ts b/packages/taler-wallet-core/src/dbtx-indexeddb.ts
@@ -464,6 +464,18 @@ export class IdbWalletTransaction implements WalletDbTransaction {
return await tx.depositGroups.iter().toArray();
}
+ async listAllRefundGroups(): Promise<WalletRefundGroup[]> {
+ return await this.tx.refundGroups.iter().toArray();
+ }
+
+ async listAllWithdrawalGroups(): Promise<WalletWithdrawalGroup[]> {
+ return await this.tx.withdrawalGroups.iter().toArray();
+ }
+
+ async listAllPurchases(): Promise<WalletPurchase[]> {
+ return await this.tx.purchases.iter().toArray();
+ }
+
async listAllPeerPullCredits(): Promise<WalletPeerPullCredit[]> {
const tx = this.tx;
return await tx.peerPullCredit.iter().toArray();
diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts
@@ -312,6 +312,12 @@ export interface WalletDbTransaction {
*/
listAllDepositGroups(): Promise<WalletDepositGroup[]>;
+ listAllRefundGroups(): Promise<WalletRefundGroup[]>;
+
+ listAllWithdrawalGroups(): Promise<WalletWithdrawalGroup[]>;
+
+ listAllPurchases(): Promise<WalletPurchase[]>;
+
listAllPeerPullCredits(): Promise<WalletPeerPullCredit[]>;
listAllPeerPullDebits(): Promise<WalletPeerPullDebit[]>;
diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts
@@ -364,7 +364,7 @@ export async function applyDevExperiment(
await tx.wtx.upsertPurchase(rec);
}
});
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
});
return;
}
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
@@ -3336,7 +3336,7 @@ async function purgeExchange(
}
// FIXME: Is this even necessary? Each deletion should already do it.
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
}
export async function deleteExchange(
diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts
@@ -67,6 +67,7 @@ import { PeerPushDebitTransactionContext } from "./pay-peer-push-debit.js";
import { RefreshTransactionContext } from "./refresh.js";
import type { LegacyWalletTxHandle, WalletExecutionContext } from "./wallet.js";
import { WithdrawTransactionContext } from "./withdraw.js";
+import { WalletDbTransaction } from "./dbtx.js";
const logger = new Logger("taler-wallet-core:transactions.ts");
@@ -538,61 +539,61 @@ export async function getTransactions(
*/
export async function rematerializeTransactions(
wex: WalletExecutionContext,
- tx: LegacyWalletTxHandle,
+ tx: WalletDbTransaction,
): Promise<void> {
logger.trace("re-materializing transactions");
- await tx.wtx.deleteAllTransactionMeta();
+ await tx.deleteAllTransactionMeta();
- await tx.peerPushDebit.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllPeerPushDebits()) {
const ctx = new PeerPushDebitTransactionContext(wex, x.pursePub);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.peerPushCredit.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllPeerPushCredits()) {
const ctx = new PeerPushCreditTransactionContext(wex, x.peerPushCreditId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.peerPullCredit.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllPeerPullCredits()) {
const ctx = new PeerPullCreditTransactionContext(wex, x.pursePub);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.peerPullDebit.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllPeerPullDebits()) {
const ctx = new PeerPullDebitTransactionContext(wex, x.peerPullDebitId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.refundGroups.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllRefundGroups()) {
const ctx = new RefundTransactionContext(wex, x.refundGroupId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.refreshGroups.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllRefreshGroups()) {
const ctx = new RefreshTransactionContext(wex, x.refreshGroupId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.withdrawalGroups.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllWithdrawalGroups()) {
const ctx = new WithdrawTransactionContext(wex, x.withdrawalGroupId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.denomLossEvents.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllDenomLossEvents()) {
const ctx = new DenomLossTransactionContext(wex, x.denomLossEventId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.depositGroups.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllDepositGroups()) {
const ctx = new DepositTransactionContext(wex, x.depositGroupId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
- await tx.purchases.iter().forEachAsync(async (x) => {
+ for (const x of await tx.listAllPurchases()) {
const ctx = new PayMerchantTransactionContext(wex, x.proposalId);
- await ctx.updateTransactionMeta(tx.wtx);
- });
+ await ctx.updateTransactionMeta(tx);
+ }
}
export type ParsedTransactionIdentifier =
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
@@ -595,7 +595,7 @@ async function migrateMaterializedTransactions(
}
}
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
await tx.config.put({
key: ConfigRecordKey.MaterializedTransactionsVersion,
@@ -913,7 +913,7 @@ async function recoverStoredBackup(
logger.info(`backup found, now importing`);
await importDb(wex.db.idbHandle(), bd);
await wex.runLegacyWalletDbTx(async (tx) => {
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
// Clear fixups. Okay since they are idempotent.
const fixups = await tx.fixups.getAll();
for (const f of fixups) {
@@ -1842,7 +1842,7 @@ async function handleImportDb(
// FIXME: This should atomically re-materialize transactions!
await importDb(wex.db.idbHandle(), req.dump);
await wex.runLegacyWalletDbTx(async (tx) => {
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
// Clear fixups. Okay since they are idempotent.
const fixups = await tx.fixups.getAll();
for (const f of fixups) {
@@ -1960,7 +1960,7 @@ export async function handleTestingRunFixup(
}
await wex.runLegacyWalletDbTx(async (tx) => {
await fixup.fn(tx);
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
});
return {};
}
@@ -3565,7 +3565,7 @@ export class InternalWalletState {
oc,
);
await wex.runLegacyWalletDbTx(async (tx) => {
- await rematerializeTransactions(wex, tx);
+ await rematerializeTransactions(wex, tx.wtx);
});
}
} catch (e) {