Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: added transaction retry logic in cockroachdb (#10032)
* added transaction retry logic in cockroachdb * added option to control max transaction retries; added delay before transaction retry; updated docs; * fixes in retry logic * enable storing queries after retrying transaction
- Loading branch information
1 parent
8795c86
commit 607d6f9
Showing
5 changed files
with
144 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Entity } from "../../../../src/decorator/entity/Entity" | ||
import { Column } from "../../../../src/decorator/columns/Column" | ||
import { PrimaryGeneratedColumn } from "../../../../src/decorator/columns/PrimaryGeneratedColumn" | ||
|
||
@Entity() | ||
export class Post { | ||
@PrimaryGeneratedColumn() | ||
id: number | ||
|
||
@Column() | ||
name: string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { DataSource } from "../../../src" | ||
import { | ||
closeTestingConnections, | ||
createTestingConnections, | ||
reloadTestingDatabases, | ||
} from "../../utils/test-utils" | ||
import { Post } from "./entity/Post.js" | ||
import { expect } from "chai" | ||
|
||
describe("github issues > #9984 TransactionRetryWithProtoRefreshError should be handled by TypeORM", () => { | ||
let dataSources: DataSource[] | ||
|
||
before(async () => { | ||
dataSources = await createTestingConnections({ | ||
entities: [Post], | ||
enabledDrivers: ["cockroachdb"], | ||
}) | ||
}) | ||
|
||
beforeEach(() => reloadTestingDatabases(dataSources)) | ||
after(() => closeTestingConnections(dataSources)) | ||
|
||
it("should retry transaction on 40001 error with 'inject_retry_errors_enabled=true'", () => | ||
Promise.all( | ||
dataSources.map(async (dataSource) => { | ||
const queryRunner = dataSource.createQueryRunner() | ||
await dataSource.query("SET inject_retry_errors_enabled = true") | ||
await queryRunner.startTransaction() | ||
|
||
const post = new Post() | ||
post.name = `post` | ||
await queryRunner.manager.save(post) | ||
await queryRunner.commitTransaction() | ||
await queryRunner.release() | ||
await dataSource.query( | ||
"SET inject_retry_errors_enabled = false", | ||
) | ||
const loadedPost = await dataSource.manager.findOneBy(Post, { | ||
id: post.id, | ||
}) | ||
expect(loadedPost).to.be.not.undefined | ||
}), | ||
)) | ||
|
||
it("should retry transaction on 40001 error", () => | ||
Promise.all( | ||
dataSources.map(async (dataSource) => { | ||
const queryRunner = dataSource.createQueryRunner() | ||
const post = new Post() | ||
post.name = "post" | ||
await queryRunner.manager.save(post) | ||
await queryRunner.release() | ||
|
||
const query = async (name: string) => { | ||
const queryRunner = dataSource.createQueryRunner() | ||
await queryRunner.startTransaction() | ||
const updatedPost = new Post() | ||
updatedPost.id = post.id | ||
updatedPost.name = name | ||
await queryRunner.manager.save(updatedPost) | ||
await queryRunner.commitTransaction() | ||
await queryRunner.release() | ||
} | ||
|
||
await Promise.all([1, 2, 3].map((i) => query(`changed_${i}`))) | ||
|
||
const loadedPost = await dataSource.manager.findOneByOrFail( | ||
Post, | ||
{ | ||
id: post.id, | ||
}, | ||
) | ||
expect(loadedPost.name).to.not.equal("post") | ||
}), | ||
)) | ||
}) |