From dff4c8f18d34117a07e7118f16219dd63934998c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 12:53:57 +0200 Subject: [PATCH 1/6] de-duplicate meta-data table creation code --- src/migration/MigrationExecutor.ts | 34 ++++++++++++------------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index 6a4ec20846..fb06c25d96 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -73,12 +73,7 @@ export class MigrationExecutor { public async executeMigration(migration: Migration): Promise { return this.withQueryRunner(async (queryRunner) => { await this.createMigrationsTableIfNotExist(queryRunner) - - // create typeorm_metadata table if it's not created yet - const schemaBuilder = this.connection.driver.createSchemaBuilder() - if (InstanceChecker.isRdbmsSchemaBuilder(schemaBuilder)) { - await schemaBuilder.createMetadataTableIfNecessary(queryRunner) - } + await this.createMetadataTableIfNotExist(queryRunner) await queryRunner.beforeMigration() await (migration.instance as any).up(queryRunner) @@ -149,7 +144,6 @@ export class MigrationExecutor { let hasUnappliedMigrations = false const queryRunner = this.queryRunner || this.connection.createQueryRunner() - // create migrations table if its not created yet await this.createMigrationsTableIfNotExist(queryRunner) // get all migrations that are executed and saved in the database @@ -191,14 +185,8 @@ export class MigrationExecutor { async executePendingMigrations(): Promise { const queryRunner = this.queryRunner || this.connection.createQueryRunner() - // create migrations table if it's not created yet await this.createMigrationsTableIfNotExist(queryRunner) - - // create the typeorm_metadata table if it's not created yet - const schemaBuilder = this.connection.driver.createSchemaBuilder() - if (InstanceChecker.isRdbmsSchemaBuilder(schemaBuilder)) { - await schemaBuilder.createMetadataTableIfNecessary(queryRunner) - } + await this.createMetadataTableIfNotExist(queryRunner) // get all migrations that are executed and saved in the database const executedMigrations = await this.loadExecutedMigrations( @@ -394,14 +382,8 @@ export class MigrationExecutor { const queryRunner = this.queryRunner || this.connection.createQueryRunner() - // create migrations table if it's not created yet await this.createMigrationsTableIfNotExist(queryRunner) - - // create typeorm_metadata table if it's not created yet - const schemaBuilder = this.connection.driver.createSchemaBuilder() - if (InstanceChecker.isRdbmsSchemaBuilder(schemaBuilder)) { - await schemaBuilder.createMetadataTableIfNecessary(queryRunner) - } + await this.createMetadataTableIfNotExist(queryRunner) // get all migrations that are executed and saved in the database const executedMigrations = await this.loadExecutedMigrations( @@ -542,6 +524,16 @@ export class MigrationExecutor { } } + /** + * Create the "typeorm_metadata" table if it's not created yet + */ + private async createMetadataTableIfNotExist(queryRunner: QueryRunner) { + const schemaBuilder = this.connection.driver.createSchemaBuilder() + if (InstanceChecker.isRdbmsSchemaBuilder(schemaBuilder)) { + await schemaBuilder.createMetadataTableIfNecessary(queryRunner) + } + } + /** * Loads all migrations that were executed and saved into the database (sorts by id). */ From 2221586b56ab44be4acb5c9a839740bceb7a45f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 12:59:43 +0200 Subject: [PATCH 2/6] always run `afterMigration` on down migrations --- src/migration/MigrationExecutor.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index fb06c25d96..e6c5c6d594 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -439,8 +439,11 @@ export class MigrationExecutor { try { if (!this.fake) { await queryRunner.beforeMigration() - await migrationToRevert.instance!.down(queryRunner) - await queryRunner.afterMigration() + try { + await migrationToRevert.instance!.down(queryRunner) + } finally { + await queryRunner.afterMigration() + } } await this.deleteExecutedMigration(queryRunner, migrationToRevert) From b3d6311ff1769755676fac3e0274e963138927b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 13:00:46 +0200 Subject: [PATCH 3/6] always run `afterMigration` on single up migrations --- src/migration/MigrationExecutor.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index e6c5c6d594..c79baded12 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -76,8 +76,11 @@ export class MigrationExecutor { await this.createMetadataTableIfNotExist(queryRunner) await queryRunner.beforeMigration() - await (migration.instance as any).up(queryRunner) - await queryRunner.afterMigration() + try { + await (migration.instance as any).up(queryRunner) + } finally { + await queryRunner.afterMigration() + } await this.insertExecutedMigration(queryRunner, migration) return migration From 19f9469c6871f27b474a93a503dc56d4210b6260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 13:03:35 +0200 Subject: [PATCH 4/6] make the migration execution code in `executePendingMigrations` more linear and readable --- src/migration/MigrationExecutor.ts | 56 ++++++++++++++---------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index c79baded12..f91fd625a8 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -324,36 +324,32 @@ export class MigrationExecutor { transactionStartedByUs = true } - await migration - .instance!.up(queryRunner) - .catch((error) => { - // informative log about migration failure - this.connection.logger.logMigration( - `Migration "${migration.name}" failed, error: ${error?.message}`, - ) - throw error - }) - .then(async () => { - // now when migration is executed we need to insert record about it into the database - await this.insertExecutedMigration( - queryRunner, - migration, - ) - // commit transaction if we started it - if (migration.transaction && transactionStartedByUs) { - await queryRunner.commitTransaction() - await queryRunner.afterMigration() - } - }) - .then(() => { - // informative log about migration success - successMigrations.push(migration) - this.connection.logger.logSchemaBuild( - `Migration ${migration.name} has been ${ - this.fake ? "(fake)" : "" - } executed successfully.`, - ) - }) + try { + await migration.instance!.up(queryRunner); + + // Now when migration is executed we need to insert record about it into the database + await this.insertExecutedMigration(queryRunner, migration); + + // Commit transaction if we started it + if (migration.transaction && transactionStartedByUs) { + await queryRunner.commitTransaction(); + await queryRunner.afterMigration(); + } + + // Log success and track the successful migration + successMigrations.push(migration); + this.connection.logger.logSchemaBuild( + `Migration ${migration.name} has been ${ + this.fake ? "(fake)" : "" + } executed successfully.` + ); + } catch (error) { + // Informative log about migration failure + this.connection.logger.logMigration( + `Migration "${migration.name}" failed, error: ${error?.message}` + ); + throw error; + } } // commit transaction if we started it From 1d5c0133056f2ed0980dea7410d89286f399bc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 13:06:35 +0200 Subject: [PATCH 5/6] always run `afterMigration` when running all pending migrations --- src/migration/MigrationExecutor.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index f91fd625a8..9cedeae1e5 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -333,7 +333,6 @@ export class MigrationExecutor { // Commit transaction if we started it if (migration.transaction && transactionStartedByUs) { await queryRunner.commitTransaction(); - await queryRunner.afterMigration(); } // Log success and track the successful migration @@ -349,13 +348,16 @@ export class MigrationExecutor { `Migration "${migration.name}" failed, error: ${error?.message}` ); throw error; + } finally { + if (migration.transaction && transactionStartedByUs) { + await queryRunner.afterMigration(); + } } } // commit transaction if we started it if (this.transaction === "all" && transactionStartedByUs) { await queryRunner.commitTransaction() - await queryRunner.afterMigration() } } catch (err) { // rollback transaction if we started it @@ -368,6 +370,9 @@ export class MigrationExecutor { throw err } finally { + if (this.transaction === "all" && transactionStartedByUs) { + await queryRunner.afterMigration() + } // if query runner was created by us then release it if (!this.queryRunner) await queryRunner.release() } From 9e457d646107b96da3102449d0e8dfc9195b8c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 13:12:56 +0200 Subject: [PATCH 6/6] fix formatting --- src/migration/MigrationExecutor.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index 9cedeae1e5..410bff1460 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -325,32 +325,32 @@ export class MigrationExecutor { } try { - await migration.instance!.up(queryRunner); + await migration.instance!.up(queryRunner) // Now when migration is executed we need to insert record about it into the database - await this.insertExecutedMigration(queryRunner, migration); + await this.insertExecutedMigration(queryRunner, migration) // Commit transaction if we started it if (migration.transaction && transactionStartedByUs) { - await queryRunner.commitTransaction(); + await queryRunner.commitTransaction() } // Log success and track the successful migration - successMigrations.push(migration); + successMigrations.push(migration) this.connection.logger.logSchemaBuild( `Migration ${migration.name} has been ${ this.fake ? "(fake)" : "" - } executed successfully.` - ); + } executed successfully.`, + ) } catch (error) { // Informative log about migration failure this.connection.logger.logMigration( - `Migration "${migration.name}" failed, error: ${error?.message}` - ); - throw error; + `Migration "${migration.name}" failed, error: ${error?.message}`, + ) + throw error } finally { if (migration.transaction && transactionStartedByUs) { - await queryRunner.afterMigration(); + await queryRunner.afterMigration() } } }