Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new transaction mode to wrap each migration in transaction #4629

Merged
merged 3 commits into from Oct 18, 2019

Conversation

nlenepveu
Copy link
Contributor

Hello people!

This work is based on the awesome work done by @garbles in #3208.


Addresses #2693

Presentation by @garbles from the original pull request:

Creates a new, backward-compatible mode for running migrations each in their own transaction. This behavior is what I think most expect as default from an ORM, so running all migrations in a single transaction seems odd. Using a single transaction also does not allow you to do certain things (in Postgres at least) if you expect to be able to run all migrations at once.

For example, if you have the following two migrations, you can never run them in a row.

export class CreateUsers0000000000002 implements MigrationInterface {
    public up(queryRunner: QueryRunner): Promise<any> {
        return queryRunner.createTable(
            new Table({
                name: "users",
                columns: [
                    {
                        name: "id",
                        type: "uuid",
                        isPrimary: true,
                        default: "uuid_generate_v4()"
                    }
                ]
            })
        );
    }

    public down(queryRunner: QueryRunner): Promise<any> {
        return queryRunner.dropTable("users");
    }
}
export class InsertUser0000000000003 implements MigrationInterface {
    public up(queryRunner: QueryRunner): Promise<any> {
        const userRepo = queryRunner.connection.getRepository<User>(User);
        return userRepo.save(new User());
    }

    public down(queryRunner: QueryRunner): Promise<any> {
        return Promise.resolve();
    }
}

The INSERT in the second migration will fail as the schema does not exist at that point. The first migration should be committed before enabling the second one to access the newly created table.

Changes to the -t flag to accept: all (run all migrations in a single transaction), each (run each migration in a separate transaction), none (run all migrations without transactions) or false (same as none).

typeorm migration:run --transaction=each
typeorm migration:run -t=each

TODO:

  • Add new tests for 'each' mode
  • Clean up code

@pleerock I addressed some of the comments you left some months ago. It would be great if you can have a look at this work!

Copy link

@garbles garbles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow fantastic. Nice work @nlenepveu !

test/github-issues/2693/issue-2693.ts Show resolved Hide resolved
@pleerock
Copy link
Member

pleerock commented Sep 5, 2019

Looks good

@antoine-pous
Copy link

@pleerock there's any due date for merging this PR? 😄

@pleerock pleerock merged commit 848fb1f into typeorm:master Oct 18, 2019
@garbles
Copy link

garbles commented Oct 18, 2019

👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏

@antoine-pous
Copy link

🎉 WOOOP!!! 🎉

@obedm503
Copy link

@pleerock There's a breaking change here. runMigrations({ transaction: true }) is no longer valid. I understand typeorm is technically not stable, but it would be nice if the breaking change was documented in the changelog.

@brunoMaurice
Copy link

I don't understand why it's not possible to use transaction for all in your exemple.
I don't know for other db, but at least for postgres it's possible to have a create and insert for the created table in the same transaction.

The connection between your two migrations is not the same ?

@pleerock
Copy link
Member

@obedm503 we might miss breaking changes easily. Please make sure to subscribe to TypeORM issues and pull requests and join others for PR reviews and left your feedback before they go into release version.

@nlenepveu
Copy link
Contributor Author

@obedm503 Strictly speaking, I'm not sure we can talk about a breaking change here. { transaction: true } has never been officially supported in the codebase, only { transaction: false } had effects. It's like saying { transaction: "on" } is no longer working.

@obedm503
Copy link

@nlenepveu the function signature was async runMigrations(options?: { transaction?: boolean }) and not async runMigrations(options?: { transaction?: false }).
{ transaction: true } was a legitimately possible value.

This was not really an issue for me. Typescript type-checking helped me catch it. I was just commenting for documentation purposes.

@nlenepveu
Copy link
Contributor Author

@obedm503 Indeed, you’re right. I missed that point.

@nlenepveu
Copy link
Contributor Author

@brunoMaurice Indeed, this issue happens when you do not use the same connection. It appears that the QueryRunner injected in the up and down methods initiate a new connection for each migration (I did not verify this in the codebase but the negative test goes in that direction).
We could have fix the initial issue differently by ensuring that the same connection is shared between all migration.

@brunoMaurice
Copy link

@nlenepveu Thanks for the answer. Did you think, it can be an enhancement to use the same QueryRunner to keep the same connection for each migration and be able to use transaction:all even if we have insert statement ?

mightyYaroslav added a commit to mightyYaroslav/typeorm that referenced this pull request Nov 26, 2019
It is the extension of pull request typeorm#4629 which allows
 applying same transaction options when running transactions in automatic mode
mightyYaroslav added a commit to mightyYaroslav/typeorm that referenced this pull request Nov 27, 2019
It is the extension of pull request typeorm#4629 which allows
applying same transaction options when running transactions in automatic mode
mightyYaroslav added a commit to mightyYaroslav/typeorm that referenced this pull request Nov 27, 2019
It is the extension of pull request typeorm#4629 which allows
applying same transaction options when running transactions in automatic mode
pleerock pushed a commit that referenced this pull request Nov 27, 2019
* feat: add migrations transaction option to connection options

It is the extension of pull request #4629 which allows
 applying same transaction options when running transactions in automatic mode

* feat: add migrations transaction option to connection options

It is the extension of pull request #4629 which allows
applying same transaction options when running transactions in automatic mode

* feat: add migrations transaction option to connection options

It is the extension of pull request #4629 which allows
applying same transaction options when running transactions in automatic mode
@nlenepveu
Copy link
Contributor Author

@brunoMaurice definitely! It should be a better option to keep a single transaction between each migration.
When releasing the code of our apps and something bad happens, we would want to revert all the changes in the database if the code finally does not go live.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants