Browse Source

IndexedDB migration: fix where the existing settings (eg. master) were not updated

migrate-dexie-to-sqlite
Trent Larson 6 days ago
parent
commit
ab2270d8b2
  1. 140
      src/services/indexedDBMigrationService.ts

140
src/services/indexedDBMigrationService.ts

@ -1087,49 +1087,48 @@ export async function migrateSettings(): Promise<MigrationResult> {
let sqliteSettingRaw: let sqliteSettingRaw:
| { columns: string[]; values: unknown[][] } | { columns: string[]; values: unknown[][] }
| undefined; | undefined;
// adjust SQL based on the accountDid key, maybe null
let conditional: string;
let preparams: unknown[];
if (!setting.accountDid) { if (!setting.accountDid) {
sqliteSettingRaw = await platformService.dbQuery( conditional = "accountDid is null";
"SELECT * FROM settings WHERE accountDid is null", preparams = [];
);
} else { } else {
sqliteSettingRaw = await platformService.dbQuery( conditional = "accountDid = ?";
"SELECT * FROM settings WHERE accountDid = ?", preparams = [setting.accountDid];
[setting.accountDid],
);
} }
sqliteSettingRaw = await platformService.dbQuery(
"SELECT * FROM settings WHERE " + conditional,
preparams,
);
logger.info("[MigrationService] Migrating one set of settings:", { logger.info("[MigrationService] Migrating one set of settings:", {
setting, setting,
sqliteSettingRaw, sqliteSettingRaw,
}); });
if (sqliteSettingRaw?.values?.length) { if (sqliteSettingRaw?.values?.length) {
// should cover the master settings, were accountDid is null // should cover the master settings, where accountDid is null
const sqliteSettings = mapColumnsToValues( delete setting.id; // don't conflict with the id in the sqlite database
sqliteSettingRaw.columns, delete setting.accountDid; // this is part of the where clause
sqliteSettingRaw.values,
) as unknown as Settings[];
const sqliteSetting = sqliteSettings[0];
let conditional: string;
let preparams: unknown[];
if (!setting.accountDid) {
conditional = "accountDid is null";
preparams = [];
} else {
conditional = "accountDid = ?";
preparams = [setting.accountDid];
}
const { sql, params } = generateUpdateStatement( const { sql, params } = generateUpdateStatement(
sqliteSetting as unknown as Record<string, unknown>, setting,
"settings", "settings",
conditional, conditional,
preparams, preparams,
); );
logger.info("[MigrationService] Updating settings", {
sql,
params,
});
await platformService.dbExec(sql, params); await platformService.dbExec(sql, params);
result.settingsMigrated++; result.settingsMigrated++;
} else { } else {
// insert new setting // insert new setting
delete setting.id; // don't conflict with the id in the sqlite database
delete setting.activeDid; // ensure we don't set the activeDid (since master settings are an update and don't hit this case) delete setting.activeDid; // ensure we don't set the activeDid (since master settings are an update and don't hit this case)
const { sql, params } = generateInsertStatement( const { sql, params } = generateInsertStatement(
setting as unknown as Record<string, unknown>, setting,
"settings", "settings",
); );
await platformService.dbExec(sql, params); await platformService.dbExec(sql, params);
@ -1140,9 +1139,6 @@ export async function migrateSettings(): Promise<MigrationResult> {
// Wait for all migrations to complete // Wait for all migrations to complete
const updatedSettings = await Promise.all(migrationPromises); const updatedSettings = await Promise.all(migrationPromises);
// Step 2: Migrate the activeDid if it exists in Dexie
await migrateActiveDid();
logger.info( logger.info(
"[MigrationService] Finished migrating settings", "[MigrationService] Finished migrating settings",
updatedSettings, updatedSettings,
@ -1283,96 +1279,6 @@ export async function migrateAccounts(): Promise<MigrationResult> {
} }
} }
/**
* Migrates the activeDid from Dexie to SQLite
*
* This function specifically handles the migration of the activeDid setting
* from the Dexie database to the SQLite database. It ensures that the
* activeDid exists in the SQLite accounts table before setting it as active.
*
* The function is designed to be called after accounts have been migrated
* to ensure the target DID exists in the SQLite database.
*
* @async
* @function migrateActiveDid
* @returns {Promise<MigrationResult>} Result of the activeDid migration
* @throws {Error} If the migration process fails
* @example
* ```typescript
* try {
* const result = await migrateActiveDid();
* if (result.success) {
* console.log('ActiveDid migration successful');
* } else {
* console.error('ActiveDid migration failed:', result.errors);
* }
* } catch (error) {
* console.error('ActiveDid migration process failed:', error);
* }
* ```
*/
export async function migrateActiveDid(): Promise<MigrationResult> {
logger.info("[MigrationService] Starting activeDid migration");
const result: MigrationResult = {
success: true,
contactsMigrated: 0,
settingsMigrated: 0,
accountsMigrated: 0,
errors: [],
warnings: [],
};
try {
// Get Dexie settings to find the activeDid
const dexieSettings = await getDexieSettings();
const masterSettings = dexieSettings.find(setting => !setting.accountDid);
if (!masterSettings?.activeDid) {
logger.info("[MigrationService] No activeDid found in Dexie master settings");
result.warnings.push("No activeDid found in Dexie settings");
return result;
}
const dexieActiveDid = masterSettings.activeDid;
logger.info("[MigrationService] Found activeDid in Dexie", {
activeDid: dexieActiveDid,
});
const platformService = PlatformServiceFactory.getInstance();
// Verify that the activeDid exists in SQLite accounts
const accountExists = await platformService.dbQuery(
"SELECT did FROM accounts WHERE did = ?",
[dexieActiveDid],
);
if (!accountExists?.values?.length) {
const errorMessage = `activeDid from Dexie (${dexieActiveDid}) not found in SQLite accounts`;
logger.error("[MigrationService]", errorMessage);
result.errors.push(errorMessage);
result.success = false;
return result;
}
// Update the master settings with the activeDid
await updateDefaultSettings({ activeDid: dexieActiveDid });
logger.info("[MigrationService] Successfully migrated activeDid", {
activeDid: dexieActiveDid,
});
result.warnings.push(`Successfully migrated activeDid: ${dexieActiveDid}`);
return result;
} catch (error) {
const errorMessage = `ActiveDid migration failed: ${error}`;
logger.error("[MigrationService]", errorMessage, error);
result.errors.push(errorMessage);
result.success = false;
return result;
}
}
/** /**
* Migrates all data from Dexie to SQLite in the proper order * Migrates all data from Dexie to SQLite in the proper order
* *

Loading…
Cancel
Save