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. 138
      src/services/indexedDBMigrationService.ts

138
src/services/indexedDBMigrationService.ts

@ -1087,27 +1087,8 @@ export async function migrateSettings(): Promise<MigrationResult> {
let sqliteSettingRaw:
| { columns: string[]; values: unknown[][] }
| undefined;
if (!setting.accountDid) {
sqliteSettingRaw = await platformService.dbQuery(
"SELECT * FROM settings WHERE accountDid is null",
);
} else {
sqliteSettingRaw = await platformService.dbQuery(
"SELECT * FROM settings WHERE accountDid = ?",
[setting.accountDid],
);
}
logger.info("[MigrationService] Migrating one set of settings:", {
setting,
sqliteSettingRaw,
});
if (sqliteSettingRaw?.values?.length) {
// should cover the master settings, were accountDid is null
const sqliteSettings = mapColumnsToValues(
sqliteSettingRaw.columns,
sqliteSettingRaw.values,
) as unknown as Settings[];
const sqliteSetting = sqliteSettings[0];
// adjust SQL based on the accountDid key, maybe null
let conditional: string;
let preparams: unknown[];
if (!setting.accountDid) {
@ -1117,19 +1098,37 @@ export async function migrateSettings(): Promise<MigrationResult> {
conditional = "accountDid = ?";
preparams = [setting.accountDid];
}
sqliteSettingRaw = await platformService.dbQuery(
"SELECT * FROM settings WHERE " + conditional,
preparams,
);
logger.info("[MigrationService] Migrating one set of settings:", {
setting,
sqliteSettingRaw,
});
if (sqliteSettingRaw?.values?.length) {
// should cover the master settings, where accountDid is null
delete setting.id; // don't conflict with the id in the sqlite database
delete setting.accountDid; // this is part of the where clause
const { sql, params } = generateUpdateStatement(
sqliteSetting as unknown as Record<string, unknown>,
setting,
"settings",
conditional,
preparams,
);
logger.info("[MigrationService] Updating settings", {
sql,
params,
});
await platformService.dbExec(sql, params);
result.settingsMigrated++;
} else {
// 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)
const { sql, params } = generateInsertStatement(
setting as unknown as Record<string, unknown>,
setting,
"settings",
);
await platformService.dbExec(sql, params);
@ -1140,9 +1139,6 @@ export async function migrateSettings(): Promise<MigrationResult> {
// Wait for all migrations to complete
const updatedSettings = await Promise.all(migrationPromises);
// Step 2: Migrate the activeDid if it exists in Dexie
await migrateActiveDid();
logger.info(
"[MigrationService] Finished migrating settings",
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
*

Loading…
Cancel
Save