Repository navigation
Fix nested transactions failing to commit with opfsLocks - #3871
Closed
hossam1244 wants to merge 2 commits into
Closed
hossam1244 wants to merge 2 commits into
hossam1244 wants to merge 2 commits into
Conversation
Nested transactions are intercepted by the same _AcquireNavigatorLock instance as their outer transaction, so the nested commit completed the shared _returnNavigatorLocks completer. The outer commit then failed with 'Bad state: Future already completed' and, because the worker had already released the transaction, the following rollback waited forever. Only the executor that created the interceptor's scope releases the navigator lock now; nested commits and rollbacks leave it to the outermost transaction. Fixes simolus3#3870
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On the web with
WasmStorageImplementation.opfsLocks, a nesteddb.transaction()makes the outer transaction fail:Root cause: nested transactions are begun through the outer
_InterceptedTransactionExecutor, so they flow through the same_AcquireNavigatorLockInterceptorinstance and therefore the same_returnNavigatorLockscompleter. The nested commit completes it; the outer commit'swhenComplete(() => _returnNavigatorLocks.complete())then throws, and because the worker has already released the transaction, the subsequentrollbackAfterExceptionwaits forever in_waitForTurn.Fixes #3870
Solution
The interceptor now receives the executor that created its scope (
ownsLock) and only completes_returnNavigatorLocksfor that executor — a nested commit or rollback leaves the lock to the outermost transaction, matching native behavior.ensureOpenwas already safe (??=dedupes the lock acquisition). The same guard coversclosefor the exclusive path.Tests
Added to the existing
@TestOn('browser')suite (drift/test/platforms/web/navigator_locks_interceptor_test.dart):nested transactions complete the outer transaction— the exact repro from the issue; without the fix it never resolves.nested transaction with rollback rolls the outer one back— the nested insert is rolled back with the outer transaction and the future completes with the error instead of hanging.Full
driftVM suite passes locally (927 tests); the browser suite runs in CI.Checklist
CHANGELOG.md.