From 248015fc06393ef4de0aa79fd27c3f0da339d851 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Mon, 23 Feb 2026 10:14:22 +0100 Subject: [PATCH] backend: add index migration functionality to MigrationService --- .../backend/src/services/migration.service.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/meet-ce/backend/src/services/migration.service.ts b/meet-ce/backend/src/services/migration.service.ts index bf34d859..4d2da3ed 100644 --- a/meet-ce/backend/src/services/migration.service.ts +++ b/meet-ce/backend/src/services/migration.service.ts @@ -28,6 +28,10 @@ export class MigrationService { * This method should be called during startup to ensure backwards compatibility. * * Uses distributed locking to ensure only one instance runs migrations in HA mode. + * + * Migration flow: + * 1) Schema/data migrations + * 2) Index synchronization (drop obsolete + create missing indexes) */ async runMigrations(): Promise { this.logger.info('Running migrations...'); @@ -48,6 +52,9 @@ export class MigrationService { // Run schema migrations to upgrade document structures await this.runSchemaMigrations(); + // Sync collection indexes to match current schema definitions + await this.runIndexMigrations(); + this.logger.info('All migrations completed successfully'); } catch (error) { this.logger.error('Error running migrations:', error); @@ -61,6 +68,59 @@ export class MigrationService { } } + /** + * Synchronizes MongoDB indexes for all registered collections. + * This removes obsolete indexes and creates missing ones according to the current schema definitions. + */ + protected async runIndexMigrations(): Promise { + this.logger.info('Running index migrations...'); + + try { + for (const registry of runtimeMigrationRegistry) { + await this.syncCollectionIndexes(registry); + } + + this.logger.info('Index migrations completed successfully'); + } catch (error) { + this.logger.error('Error running index migrations:', error); + throw error; + } + } + + /** + * Synchronizes indexes for a single collection. + * + * @param registry - The collection migration registry containing model and collection metadata + */ + protected async syncCollectionIndexes( + registry: CollectionMigrationRegistry + ): Promise { + this.logger.info(`Syncing indexes for collection: ${registry.collectionName}`); + + const indexesBeforeSync = await registry.model.collection.indexes(); + const indexNamesBeforeSync = new Set(indexesBeforeSync.map((index) => index.name)); + + const droppedIndexes = await registry.model.syncIndexes(); + + const indexesAfterSync = await registry.model.collection.indexes(); + const indexNamesAfterSync = new Set(indexesAfterSync.map((index) => index.name)); + + const createdIndexes = Array.from(indexNamesAfterSync).filter( + (indexName) => !indexNamesBeforeSync.has(indexName) + ); + + if (droppedIndexes.length === 0 && createdIndexes.length === 0) { + this.logger.debug(`No index changes for collection: ${registry.collectionName}`); + return; + } + + this.logger.info( + `Index sync for ${registry.collectionName}: ` + + `dropped=${droppedIndexes.length} [${droppedIndexes.join(', ')}], ` + + `created=${createdIndexes.length} [${createdIndexes.join(', ')}]` + ); + } + /** * Runs all schema migrations to upgrade document structures to the latest version. * Processes each collection in the registry and executes pending migrations.