Conversation
The unrestorable busy wait test assumed that its connection already had a Ruby busy handler, which PRAGMA busy_timeout reads as 0. Rails 7.2 and later install that handler on each new connection, and an earlier sync call installs it too. A new Rails 7.1 connection instead uses SQLite's own busy_timeout, which PRAGMA reads as 5000. When the test ran first on Rails 7.1, the adapter correctly took the restorable path and put back SQLite's own wait. That wait holds the Ruby VM lock, so the releaser thread could not release the write lock, and the write raised SQLite3::BusyException after 5 s. Seed 11785 failed every time; CI run 35874660739 failed the same way. Install the handler in the test and assert that PRAGMA reads 0, so the test checks the unrestorable path on every Rails version and order.
|
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.
Summary
test_sync_leaves_an_unrestorable_busy_wait_alonefailed on Rails 7.1 when it ran before any other test had touched its connection. CI run 35874660739 failed this way, and seed 11785 fails every time onmain.The test checks that a sync call leaves alone a busy wait that the adapter cannot read back. It stubs
configured_busy_handler_timeouttonil, so the adapter readsPRAGMA busy_timeout. The test assumed that its connection already had a Ruby busy handler, whichPRAGMA busy_timeoutreads as 0:PRAGMA busy_timeoutbusy_handler_timeout=On a new Rails 7.1 connection, the adapter correctly took the restorable path and put back SQLite's own wait. That wait does not release the Ruby VM lock, so the releaser thread in
write_while_write_lock_is_briefly_heldcould not release the write lock. The write raisedSQLite3::BusyExceptionafter the full 5 s.The test now installs the Ruby busy handler on its connection and asserts that
PRAGMA busy_timeoutreads 0. It checks the unrestorable path on every Rails version and in every test order. Only the test changes; the adapter behaved correctly.Compatibility
Test-only change. No runtime, API, or migration effect. Not applicable to
solid-objects-js, which has no Rails connection or Ruby VM lock.Validation
ActiveRecord::StatementInvalid: SQLite3::BusyException: database is lockedatwrite_while_write_lock_is_briefly_heldafter about 6 s.bundle exec rake test TESTOPTS="--seed=11785": 797 runs, 1 error (this test,BusyException).return nil unless pragma_timeout.positive?fromSqlite#restorable_busy_waitmakes the adapter overwrite the handler. The changed test then fails withSQLite3::BusyExceptionon Rails 7.1.6 and 8.1.3.1.bundle exec rake: 797 runs, 2,707 assertions, 0 failures/errors, 28 skips. Standard, RuboCop, RBS validation, Steep, and Brakeman passed.Rails 7.1 runs used
RAILS_VERSION=7.1 bundle lock --update --local, as the CI compatibility job does.