Skip to content

fix(adapter-better-sqlite3): recover from failed transactions - #29955

Open
wehamed wants to merge 1 commit into
prisma:v7from
wehamed:fix/better-sqlite3-transaction-recovery
Open

fix(adapter-better-sqlite3): recover from failed transactions#29955
wehamed wants to merge 1 commit into
prisma:v7from
wehamed:fix/better-sqlite3-transaction-recovery

Conversation

@wehamed

@wehamed wehamed commented Aug 10, 2026

Copy link
Copy Markdown

Linked issue

Fixes #29933

Summary

A failed SQLite COMMIT could leave the shared better-sqlite3 connection
inside an open transaction, while a later BEGIN failure could leak the
adapter mutex permanently.

This makes rollback() perform best-effort connection cleanup when SQLite
still reports an active transaction, and releases the mutex when BEGIN
fails. Successful transaction behavior and the existing
usePhantomQuery: false contract are unchanged.

Testing performed

  • Added focused transaction regression coverage for successful commit and
    rollback, failed-COMMIT recovery, failed-BEGIN mutex release, and cleanup
    failure behavior.
  • Focused transaction suite: 5/5 passed.
  • End-to-end adapter-better-sqlite3: a single SQLITE_BUSY at COMMIT permanently breaks all subsequent transactions and silently loses acknowledged writes #29933 reproduction passed in rollback-journal mode:
    • the blocked COMMIT fails with the original SQLITE_BUSY-mapped error
    • the adapter connection is no longer left inside a transaction
    • subsequent transactions succeed
    • no P2028 mutex poison occurs
    • subsequent acknowledged writes remain committed on a fresh connection
  • Mutation checks confirmed both regressions return when either the failed-BEGIN
    release or failed-COMMIT cleanup is removed.
  • Typecheck passed.
  • ESLint passed for the affected files.
  • Prettier check passed.
  • git diff --check passed.

The full adapter package suite has one pre-existing
errors.test.ts > UniqueConstraintViolation failure caused by the local
better-sqlite3 12.6.0 error-message shape. The same failure was reproduced on
a pristine v7 checkout; the new transaction tests remain green.

Skill update

n/a — bug fix for existing adapter transaction behavior; no skill changes required.

Checklist

  • All commits are signed off with DCO.
  • The change is scoped to one logical concern.
  • Regression tests are included.
  • No Linear ticket exists for this external GitHub issue; the title follows
    the conventional fix(scope): form.
  • The Skill update section is filled in.

Notes for the reviewer

With usePhantomQuery: false, the transaction manager owns normal
COMMIT/ROLLBACK SQL and the adapter's commit() / rollback() methods are
lifecycle callbacks.

The cleanup added here therefore runs only when rollback() observes that
better-sqlite3 is still inside a transaction, which is the failed-COMMIT case.
Cleanup is best-effort so a secondary ROLLBACK failure cannot replace the
original transaction error.

The misleading SQLITE_BUSYSocketTimeout mapping is intentionally out
of scope.

Summary by CodeRabbit

  • Bug Fixes

    • Improved transaction rollback handling with best-effort cleanup when SQLite remains in an active transaction.
    • Preserved the original transaction error when cleanup also encounters a failure.
    • Improved recovery after busy database errors during commit.
    • Ensured transaction locks are released when startup or cleanup fails.
  • Tests

    • Added comprehensive coverage for commit, rollback, failure recovery, and lock-release scenarios.

Signed-off-by: Hamed Elaraby <qef0@hotmail.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0143bde6-551f-4663-ba1e-4c9bc5ef691d

📥 Commits

Reviewing files that changed from the base of the PR and between 668b2dd and 1246ccd.

📒 Files selected for processing (2)
  • packages/adapter-better-sqlite3/src/better-sqlite3.test.ts
  • packages/adapter-better-sqlite3/src/better-sqlite3.ts

📝 Walkthrough

Walkthrough

The better-sqlite3 adapter now performs SQLite rollback cleanup after failed commits and releases its mutex when transaction startup fails. Tests cover commit, rollback, SQLITE_BUSY recovery, cleanup failures, and BEGIN failures.

Changes

SQLite transaction recovery

Layer / File(s) Summary
Rollback cleanup and recovery
packages/adapter-better-sqlite3/src/better-sqlite3.ts, packages/adapter-better-sqlite3/src/better-sqlite3.test.ts
rollback() issues ROLLBACK when SQLite remains in a transaction and logs cleanup failures without masking the original error. Tests cover commit, rollback, SQLITE_BUSY recovery, and rollback cleanup failures.
Transaction startup mutex handling
packages/adapter-better-sqlite3/src/better-sqlite3.ts, packages/adapter-better-sqlite3/src/better-sqlite3.test.ts
startTransaction() releases the mutex when BEGIN or transaction construction fails. Tests verify that later attempts do not hang after a failed BEGIN.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: lgtm

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the transaction recovery fix implemented in the adapter.
Linked Issues check ✅ Passed The changes implement transaction cleanup, mutex release, and recovery after failed COMMIT or BEGIN operations required by issue [#29933].
Out of Scope Changes check ✅ Passed The implementation and regression tests are directly related to the transaction recovery requirements in issue [#29933].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

daltino

This comment was marked as resolved.

@aqrln aqrln added this to the 7.10.0 milestone Aug 11, 2026

@SevInf SevInf left a comment

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.

Thank you for submitting PR, we appreciate it.
I don't think it is a reliable fix for the issue though. If either COMMIT or ROLLBACK failed we are not sure if connection is stuck in transactional state or not and best effort attempts to repair it might not be enough. I feel like in those 2 cases our only option to ensure next query succeeds is killing and re-creating the connection. Could you update the PR to do that instead?

@SevInf SevInf left a comment

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.

(See above for requested changes)

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.

4 participants