- Notifications
You must be signed in to change notification settings - Fork2k
fix(adapter-mssql): prevent connection pool exhaustion and EREQINPROG errors by serializing commit/rollback#28825
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Conversation
coderabbitaibot commentedDec 3, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
WalkthroughAddresses a race condition in MSSQL adapter transaction handling by protecting commit and rollback operations with mutex locks to prevent concurrent access, and adds a test validating rollback waits for in-progress queries to complete. Changes
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (2)**/*.ts📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.ts📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (4)📚 Learning: 2025-12-03T09:46:36.091ZApplied to files:
📚 Learning: 2025-12-03T09:46:36.091ZApplied to files:
📚 Learning: 2025-12-03T09:46:36.091ZApplied to files:
📚 Learning: 2025-12-03T09:46:36.091ZApplied to files:
🧬 Code graph analysis (1)packages/adapter-mssql/src/transaction.test.ts (2)
🔇 Additional comments (5)
Thanks for usingCodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
packages/adapter-mssql/src/mssql.ts(2 hunks)packages/adapter-mssql/src/transaction.test.ts(1 hunks)packages/cli/src/Init.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/adapter-mssql/src/transaction.test.ts (2)
packages/adapter-mssql/src/mssql.ts (1)
PrismaMssqlAdapter(128-177)packages/client-engine-runtime/src/transaction-manager/transaction-manager.ts (1)
tx(239-295)
packages/adapter-mssql/src/mssql.ts (3)
packages/client/tests/e2e/_utils/run.ts (1)
release(248-254)packages/driver-adapter-utils/src/types.ts (1)
SqlDriverAdapter(248-268)packages/driver-adapter-utils/src/index.ts (1)
SqlDriverAdapter(28-28)
🔇 Additional comments (3)
packages/cli/src/Init.ts (1)
116-139:Lazy-loading dev server modules only when needed looks correctGuarding the dynamic
import('@prisma/dev')/import('@prisma/dev/internal/state')behindurl === undefinedpreserves existing behavior for all code paths while avoiding unnecessary module load when a URL is already provided. ThedefaultEnvcallers always pass a defined URL except for the “local Prisma Postgres” default case, so the change is behaviorally equivalent and lower overhead.packages/adapter-mssql/src/mssql.ts (2)
92-119:Serializing commit/rollback with the same mutex as performIO aligns with the intended fixUsing
this.#mutex.acquire()in bothcommitandrollback, withrelease()in afinallyblock, correctly ensures that commits/rollbacks cannot run while a transactional request is in progress, and that queries cannot start while a close operation is running. This should prevent the EREQINPROG “request in progress” race while still preserving the existing EABORT handling inrollback.
128-210:ExportingPrismaMssqlAdapteris consistent with its factory and useful for testsMaking
PrismaMssqlAdapteran exported class matches its use as the concrete return type ofPrismaMssqlAdapterFactory.connect()and enables direct instantiation in tests and advanced consumers. Just be aware this effectively promotes it to part of the package’s public API surface going forward.
Uh oh!
There was an error while loading.Please reload this page.
aqrln left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks so much! The change in the logic itself looks good to me, but there are some issues in the test and unrelated changes that need to be moved out of this PR.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
devanshuprakash commentedDec 3, 2025
I've addressed your feedback:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
packages/adapter-mssql/src/transaction.test.ts (3)
29-29:Test suite name should be more specific.The suite name "transaction regression" doesn't clearly indicate what race condition is being guarded against. Consider a more descriptive name like:
-describe('PrismaMssqlAdapter transaction regression', () => {+describe('PrismaMssqlAdapter: rollback during active query (EREQINPROG prevention)', () => {
30-30:Test name contradicts the expected behavior.The test name says "should reproduce EREQINPROG" but line 87 expects rollback to resolve without error. With the mutex fix in place, the test verifies that EREQINPROG doesnot occur. Consider renaming to reflect the guarded regression:
- it('should reproduce EREQINPROG when rollback is called during active query', async () => {+ it('does not throw EREQINPROG when rollback is called during an active query', async () => {
62-73:Avoid usingas anytype assertion.The
as anytype assertion on line 73 bypasses type safety. Consider defining a proper type or interface for the mocked transaction object:typeMockTransaction={on:()=>voidbegin:()=>Promise<void>commit:()=>Promise<void>rollback:ReturnType<typeofvi.fn>request:()=>{input:()=>voidquery:ReturnType<typeofvi.fn>arrayRowMode:boolean}}pool.transaction=()=>({on:()=>{},begin:async()=>{},commit:async()=>{},rollback:rollbackMock,request:()=>({input:()=>{},query:queryMock,arrayRowMode:false,}),})asMockTransaction
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
packages/adapter-mssql/src/transaction.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript for new code in the Prisma monorepo
Files:
packages/adapter-mssql/src/transaction.test.ts
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.ts: Place test files alongside source files with.test.tsnaming convention, which are excluded from build output via esbuild config
Inline snapshots should be kept concise unless the exact message matters
Files:
packages/adapter-mssql/src/transaction.test.ts
🧠 Learnings (1)
📚 Learning: 2025-12-03T09:46:36.091Z
Learnt from: CRRepo: prisma/prisma PR: 0File: AGENTS.md:0-0Timestamp: 2025-12-03T09:46:36.091ZLearning: Applies to packages/migrate/src/__tests__/**/*.test.ts : Use `ctx.setDatasource()` test helper to override config.datasource for connection-specific test scenariosApplied to files:
packages/adapter-mssql/src/transaction.test.ts
🧬 Code graph analysis (1)
packages/adapter-mssql/src/transaction.test.ts (2)
packages/adapter-mssql/src/mssql.ts (1)
PrismaMssqlAdapter(128-177)packages/client-engine-runtime/src/transaction-manager/transaction-manager.ts (1)
tx(239-295)
🔇 Additional comments (2)
packages/adapter-mssql/src/transaction.test.ts (2)
1-4:LGTM!Imports are appropriate for the test setup. The newly exported
PrismaMssqlAdapterclass enables this unit test.
6-27:LGTM!The mocking strategy appropriately isolates the adapter behavior for testing. The minimal implementations and override pattern are standard for unit tests.
Uh oh!
There was an error while loading.Please reload this page.
devanshuprakash commentedDec 3, 2025
@aqrln |
708f39f to5c110e8Compare
Uh oh!
There was an error while loading.Please reload this page.
This PR fixes a critical issue in
@prisma/adapter-mssqlwhereEREQINPROGerrors and connection pool exhaustion could occur under load.Root Cause
The issue was caused by a race condition inside the
MssqlTransactionclass:commitandrollbackmethods did not acquire the mutex that serializes access to the underlying MSSQL connection.commitorrollbackcould execute while a query was still in progress (e.g., a slow query).EREQINPROG: Can't rollback transaction. There is a request in progress.
Fix
This PR ensures:
commitacquires the mutex before executing.rollbackacquires the mutex before executing.This guarantees that these methods wait for any active queries to finish, removing the race condition.
Changes
packages/adapter-mssql/src/mssql.tsMssqlTransaction.committo acquire the mutex.MssqlTransaction.rollbackto acquire the mutex.PrismaMssqlAdapterto enable unit testing.packages/adapter-mssql/src/transaction.test.tsEREQINPROGerror and allows the rollback to complete successfully after the query finishes.Verification
Tested via:
pnpm test packages/adapter-mssql/src/transaction.test.ts
Output:
✓ src/transaction.test.ts (1 test) 103ms
✓ PrismaMssqlAdapter reproduction > should reproduce EREQINPROG when rollback is called during active query 103ms
Fixes#28812
Summary by CodeRabbit
Release Notes
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.