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

fix: fix "Cannot commit, no transaction is active" error in sql.js #9234

Merged
merged 2 commits into from
Sep 19, 2022

Conversation

Obiwan1995
Copy link
Contributor

@Obiwan1995 Obiwan1995 commented Jul 22, 2022

Fixes: #9100

Description of change

When calling autoSave in a transaction, typeorm automatically closes the transaction in the export method. Therefore, when calling commitTransaction, the transaction is already committed and sqljs throws an exception "Cannot commit, no transaction is active".
This fix disables autoSave during the transaction to avoid this. Of course, autoSave is still called after the transaction, when calling commit.

There was another PR for this issue (#9101) but this fix is not working when saving the database inside a transaction. If we call a find on the repository, typeorm releases the connection and it's calling autoSave. Waiting for the transaction to finish before saving was not working as we wait indefinitely.

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • npm run format to apply prettier formatting
  • npm run test passes with this change
  • This pull request links relevant issues as Fixes #0000
  • There are new or updated unit tests validating the change N/A
  • Documentation has been updated to reflect this change N/A
  • The new commits follow conventions explained in CONTRIBUTING.md

*/
async autoSave() {
if (this.options.autoSave) {
if (this.options.autoSave && !this.queryRunner?.isTransactionActive) {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we throw an error if one tries to autoSave during active transaction? Imagine someone called autoSave but it didn't save anything if transaction was active, and user still thinks everything was saved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I get your point though it would be a bit tricky to do it as this method is automatically called on query runner release if database has changed (code from SqljsQueryRunner.ts):

private async flush() {
    if (this.isDirty) {
            await this.driver.autoSave()
            this.isDirty = false
    }
}

async release(): Promise<void> {
    await this.flush()
    return super.release()
}

If we throw an error everytime this gets called within a transaction, we will end up with tons of errors as a simple update on the repository during a transaction will trigger it.

Is there a way to inform the user without throwing an error?

Copy link
Member

Choose a reason for hiding this comment

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

okay, another question:

shouldn't we add the proposed check into commitTransaction override?:

    async commitTransaction(): Promise<void> {
        await super.commitTransaction()
        if (this.isTransactionActive === false)
            await this.flush()
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You want to add it there to ensure that the database is saved after the transaction?

Currently, COMMIT sets isDirty to true. Then, when the query runner is released after the query, it automatically flushes the database as there is no active transaction.

So, database is already saved after transaction but it would be easier to understand I admit.

Copy link
Member

@pleerock pleerock Aug 25, 2022

Choose a reason for hiding this comment

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

It makes sense to have it there I think. We flush after the transaction. And we do it only if transaction was committed.

@Obiwan1995
Copy link
Contributor Author

Any news on merging this?
My team had to fork the repository because of this so it would be nice to have it in the next release.

@pleerock pleerock merged commit 749809a into typeorm:master Sep 19, 2022
@pleerock
Copy link
Member

Thank you for contribution! 🎉

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.

SQLjs 'cannot commit - no transaction is active'
2 participants