diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index 6a4ec20846b..410bff1460b 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -73,16 +73,14 @@ 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) - await queryRunner.afterMigration() + try { + await (migration.instance as any).up(queryRunner) + } finally { + await queryRunner.afterMigration() + } await this.insertExecutedMigration(queryRunner, migration) return migration @@ -149,7 +147,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 +188,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( @@ -333,42 +324,40 @@ 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() + } + + // 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 + } 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 @@ -381,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() } @@ -394,14 +386,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( @@ -457,8 +443,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) @@ -542,6 +531,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). */