commit e9a199544f564e4acc38397c20ffef09ef6548a8
parent 15f2856f1fab6bc115de155c9a97a512ae856f37
Author: Florian Dold <dold@taler.net>
Date: Thu, 6 Aug 2026 20:33:23 +0200
wallet-cli: drop the file-to-file database conversion
Superseded by the in-place migration: a second file to swap into place is a
step the wallet can take itself, and one the mobile wallets never could.
Issue: https://bugs.taler.net/n/11718
Diffstat:
3 files changed, 2 insertions(+), 109 deletions(-)
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
@@ -84,7 +84,6 @@ import {
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import { JsonMessage, runRpcServer } from "@gnu-taler/taler-util/twrpc";
import {
- convertWalletDbFile,
createNativeWalletHost2,
inspectWalletDbPath,
nativeCrypto,
@@ -2916,48 +2915,6 @@ const advancedCli = walletCli.subcommand("advancedArgs", "advanced", {
addApiCommand(advancedCli, "advancedApi", "api");
advancedCli
- .subcommand("convertDb", "convert-db", {
- help: "Convert a wallet database between storage backends.",
- mark: "experimental",
- })
- .requiredArgument("source", clk.STRING, {
- help: "Existing wallet database file to read.",
- })
- .requiredArgument("dest", clk.STRING, {
- help: "Fresh file to write the converted database to (must not exist).",
- })
- .flag("toIdb", ["--to-indexeddb"], {
- help: "Convert native-sqlite to IndexedDB instead of the default IndexedDB to native-sqlite.",
- })
- .action(async (args) => {
- // The source is never written to; the conversion goes into a fresh file
- // and swapping it into place stays an explicit step for the operator.
- const direction = args.convertDb.toIdb ? "to-idb" : "to-native";
- const report = await convertWalletDbFile(
- args.convertDb.source,
- args.convertDb.dest,
- direction,
- );
- console.log(
- j2s({
- direction,
- source: args.convertDb.source,
- dest: args.convertDb.dest,
- totalRecords: report.totalRecords,
- copied: report.copied,
- }),
- );
- console.log(`conversion complete and verified; the original is untouched.`);
- console.log(
- `to switch the wallet over, move ${args.convertDb.dest} into place` +
- ` yourself` +
- (direction === "to-native"
- ? ` and run the wallet with TALER_WALLET_NATIVE_DB=1.`
- : ` and run the wallet without TALER_WALLET_NATIVE_DB.`),
- );
- });
-
-advancedCli
.subcommand("dbMigrationInfo", "db-migration-info", {
help: "Show which schema a wallet database file uses.",
mark: "experimental",
diff --git a/packages/taler-wallet-core/src/host-impl.node.ts b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -24,7 +24,6 @@
*/
import {
BridgeIDBFactory,
- createSqliteBackend,
createSqliteBackendOverDb,
shimIndexedDB,
} from "@gnu-taler/idb-bridge";
@@ -42,7 +41,6 @@ import {
getSqlite3FilenameFromStoragePath,
} from "./host-common.js";
import { openNativeSqliteWalletDb } from "./dbtx-sqlite.js";
-import { convertWalletDb, DbConversionReport } from "./db-converter.js";
import { Wallet } from "./wallet.js";
import { WalletDbHandle } from "./dbtx-handle.js";
import {
@@ -174,67 +172,6 @@ export async function rollbackWalletDbMigration(dbPath: string): Promise<void> {
*
* Extended version that allows getting DB stats.
*/
-/**
- * Convert a wallet database between backends, file to file.
- *
- * The direction is chosen by `direction`: "to-native" reads an IndexedDB
- * emulation file and writes a native sqlite file, "to-idb" the reverse.
- * The source is opened read-only in effect (nothing writes to it) and the
- * destination must not exist yet: conversion goes into a fresh file, and
- * swapping files afterwards is the caller's explicit, reversible step.
- */
-export async function convertWalletDbFile(
- sourcePath: string,
- destPath: string,
- direction: "to-native" | "to-idb",
-): Promise<DbConversionReport> {
- if (fs.existsSync(destPath)) {
- throw Error(
- `destination ${destPath} already exists; conversion only writes to a` +
- ` fresh file`,
- );
- }
- if (!fs.existsSync(sourcePath)) {
- throw Error(`source database ${sourcePath} does not exist`);
- }
-
- const openIdb = async (filename: string) => {
- const imp = await createNodeHelperSqlite3Impl();
- const backend = await createSqliteBackend(imp, { filename });
- return new IdbWalletDbHandle(new BridgeIDBFactory(backend));
- };
- const openNative = async (filename: string) => {
- const imp = await createNodeHelperSqlite3Impl();
- return new SqliteWalletDbHandle(
- await openNativeSqliteWalletDb(await imp.open(filename)),
- );
- };
-
- const src =
- direction === "to-native"
- ? await openIdb(sourcePath)
- : await openNative(sourcePath);
- const dst =
- direction === "to-native"
- ? await openNative(destPath)
- : await openIdb(destPath);
-
- try {
- return await convertWalletDb(src, dst);
- } catch (e) {
- // A failed conversion must not leave a half-written destination around
- // to be mistaken for a converted database.
- await dst.close();
- fs.rmSync(destPath, { force: true });
- // WAL side files of a native destination.
- fs.rmSync(`${destPath}-wal`, { force: true });
- fs.rmSync(`${destPath}-shm`, { force: true });
- throw e;
- } finally {
- await src.close();
- }
-}
-
export async function createNativeWalletHost2(
args: DefaultNodeWalletArgs = {},
): Promise<{
diff --git a/packages/taler-wallet-core/src/index.node.ts b/packages/taler-wallet-core/src/index.node.ts
@@ -27,9 +27,8 @@ export * from "./crypto/workers/synchronousWorkerFactoryPlain.js";
export * from "./dbtx-bench.js";
export { makeIdbRunner, makeSqliteRunner } from "./dbtx-runners.js";
-// Backend-to-backend database conversion. Node-only: it opens both
-// backends' files side by side.
-export { convertWalletDbFile } from "./host-impl.node.js";
+// The record-by-record copy between backends, which the in-place migration
+// runs. Node-only: the runners spawn the sqlite helper process.
export { convertWalletDb } from "./db-converter.js";
export type { DbConversionReport } from "./db-converter.js";