fix(adapter-mssql): prevent connection pool exhaustion and EREQINPROG errors by serializing commit/rollback#28825
Conversation
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 using CodeRabbit! 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.
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.
aqrln
left a comment
There was a problem hiding this comment.
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.
|
I've addressed your feedback:
|
There was a problem hiding this comment.
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 does not 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:type MockTransaction = { on: () => void begin: () => Promise<void> commit: () => Promise<void> rollback: ReturnType<typeof vi.fn> request: () => { input: () => void query: ReturnType<typeof vi.fn> arrayRowMode: boolean } } pool.transaction = () => ({ on: () => {}, begin: async () => {}, commit: async () => {}, rollback: rollbackMock, request: () => ({ input: () => {}, query: queryMock, arrayRowMode: false, }), }) as MockTransaction
📜 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: CR
Repo: prisma/prisma PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T09:46:36.091Z
Learning: Applies to packages/migrate/src/__tests__/**/*.test.ts : Use `ctx.setDatasource()` test helper to override config.datasource for connection-specific test scenarios
Applied 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.
|
@aqrln |
708f39f to
5c110e8
Compare
|
@aqrln What's the status of this fix? Currently experiencing lots of |
|
@devanshuprakash We patched our adapter with these changes about a week ago and haven't seen the using v16.16.3 "rust-free" |
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.