Skip to content

fix(adapter-mssql): acquire mutex in commit/rollback to prevent EREQINPROG error#29119

Closed
MarkusLund wants to merge 1 commit intoprisma:mainfrom
MarkusLund:fix/adapter-mssql-race-condition
Closed

fix(adapter-mssql): acquire mutex in commit/rollback to prevent EREQINPROG error#29119
MarkusLund wants to merge 1 commit intoprisma:mainfrom
MarkusLund:fix/adapter-mssql-race-condition

Conversation

@MarkusLund
Copy link
Copy Markdown
Contributor

@MarkusLund MarkusLund commented Feb 2, 2026

Description

Fix race condition in MssqlTransaction where commit() or rollback() can be called while a query is still in progress, causing the mssql driver to throw EREQINPROG error.

Problem

The mssql driver throws EREQINPROG ("Can't rollback transaction. There is a request in progress.") when commit() or rollback() is invoked while a query is executing. This commonly occurs when a transaction times out during an in-flight query.

In the current implementation:

  • performIO() acquires a mutex before executing queries
  • commit() and rollback() do not acquire the mutex

This allows commit()/rollback() to race with active queries.

Solution

Modified commit() and rollback() to acquire the same mutex that performIO() uses. This ensures they wait for any active query to complete before executing.

Changes

  • packages/adapter-mssql/src/mssql.ts: Added mutex acquisition to commit() and rollback() methods
  • packages/adapter-mssql/src/mssql.test.ts: Added unit tests validating the mutex serialization behavior

Fixes #28994

Summary by CodeRabbit

  • Bug Fixes

    • Commit and rollback now reliably wait for in‑flight queries using serialization, preventing race conditions and reducing unexpected transaction failures; improved handling of aborted (EABORT) and other error cases.
  • Tests

    • Added comprehensive tests validating transaction serialization, concurrent query behavior, correct ordering of commit/rollback relative to running queries, and proper handling/rethrowing of abort and non-abort errors.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 2, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 2, 2026

Walkthrough

Adds mutex-based serialization to MSSQL transaction commit and rollback, and a test suite that reproduces the pre-fix race and verifies serialization, ordering, and error handling (EABORT, non-EABORT, concurrent queries) with and without the mutex.

Changes

Cohort / File(s) Summary
Transaction Mutex Implementation
packages/adapter-mssql/src/mssql.ts
Wraps commit() and rollback() with mutex acquisition/release. rollback() preserves prior EABORT handling while executed under the lock; both methods release the mutex in finally blocks.
Mutex Serialization Test Suite
packages/adapter-mssql/src/mssql.test.ts
Adds tests and mocks that reproduce the race when mutex is disabled (EREQINPROG), and verify that enabling the mutex serializes queryRaw, commit, and rollback, asserts event ordering, checks EABORT passthrough and non-EABORT rethrows, and tests concurrent queries followed by commit.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(adapter-mssql): acquire mutex in commit/rollback to prevent EREQINPROG error' directly and clearly describes the main change: acquiring a mutex in commit/rollback methods to prevent the EREQINPROG error.
Linked Issues check ✅ Passed The code changes directly address all key objectives from issue #28994: mutex acquisition prevents concurrent execution of commit/rollback with in-flight queries, thereby preventing the EREQINPROG error that made the adapter unusable.
Out of Scope Changes check ✅ Passed All changes are scoped to the stated objective: modifications to mssql.ts implement mutex acquisition in commit/rollback, and test additions in mssql.test.ts verify the fix without introducing unrelated changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In `@packages/adapter-mssql/src/mssql.test.ts`:
- Around line 173-182: Add a unit test that mirrors the rollback
error-propagation test but for commit: mockTransaction.commit should be mocked
to return a rejected Promise with an Error having message "Connection lost" and
code 'ECONNCLOSED', then call createTransaction(true) and assert that
tx.commit() rejects with that error message; reference mockTransaction.commit
and the commit method on the transaction created by createTransaction.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 4, 2026

Merging this PR will improve performance by ×30

⚡ 1 improved benchmark
✅ 40 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
compile findUnique simple 26,137.5 µs 875.8 µs ×30

Comparing MarkusLund:fix/adapter-mssql-race-condition (70e179c) with main (36b57cb)

Open in CodSpeed

@MarkusLund MarkusLund force-pushed the fix/adapter-mssql-race-condition branch from f37b4e1 to 4cc03b8 Compare February 5, 2026 09:22
@jacek-prisma
Copy link
Copy Markdown
Contributor

Hi @MarkusLund, thanks for the pull request. Before we merge it though, could you sign the CLA?

@jacek-prisma
Copy link
Copy Markdown
Contributor

The PR looks good, I think it can be merged when the CLA is signed and the one minor comment I left is addressed.

@MarkusLund MarkusLund force-pushed the fix/adapter-mssql-race-condition branch from 4cc03b8 to 70e179c Compare February 5, 2026 19:57
@MarkusLund
Copy link
Copy Markdown
Contributor Author

CLA signed, @jacek-prisma 👍

},

async commit() {
if (useMutexForCommitRollback) {
Copy link
Copy Markdown
Contributor

@jacek-prisma jacek-prisma Feb 6, 2026

Choose a reason for hiding this comment

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

useMutexForCommitRollback is now always true, so we can remove the parameter and the unreachable branches

}
}

describe('with mutex (the fix)', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

probably don't need the nested describe here

jacek-prisma added a commit that referenced this pull request Feb 6, 2026
…NPROG error (#29141)

Cleanup of #29119

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed race condition in MSSQL transaction handling where commit() or
rollback() could fail when queries are in progress.

* **Tests**
* Added comprehensive test suite for transaction serialization to
validate proper operation ordering and error handling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Markus Haave Lund <markus.lund@bekk.no>
@jacek-prisma
Copy link
Copy Markdown
Contributor

Included in #29141

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.

@prisma/adapter-mssql (Prisma 7) is unusable

3 participants