Skip to content

Reset busy SQLite statements before returning pooled leases - #21

Open
daniel-vacic wants to merge 1 commit into
powersync-ja:mainfrom
daniel-vacic:codex/wal-pool-repro
Open

Reset busy SQLite statements before returning pooled leases#21
daniel-vacic wants to merge 1 commit into
powersync-ja:mainfrom
daniel-vacic:codex/wal-pool-repro

Conversation

@daniel-vacic

Copy link
Copy Markdown
Contributor

What changed

  • reset every busy SQLite statement before a reader or writer lease becomes
    available again
  • roll back any explicit transaction that survives lease scope
  • add a file-backed WAL regression proving a stepped reader no longer strands
    checkpoint frames while autocommit is true
  • cover explicit reader and writer transaction cleanup

Root cause

A stepped statement can retain an implicit WAL read transaction while
sqlite3_get_autocommit() still returns true. OwnedConnectionLease::drop
previously returned the connection directly to the pool, so the stale snapshot
could survive indefinitely and cap nBackfill.

This addresses #19. Cleanup runs at the physical pool boundary, after the lease
owner has finished and before another caller can acquire the handle.

Validation

  • rustup run 1.96.0 cargo test -p powersync
  • rustup run 1.96.0 cargo test -p powersync --test wal_pool_repro -- --nocapture
  • rustup run 1.96.0 cargo clippy -p powersync --all-targets -- -D warnings
  • rustup run 1.96.0 cargo fmt --all -- --check

The regression failed before the fix with log=14, checkpointed=3; after
explicit finalization it reached checkpointed=14. It passes with pool-boundary
cleanup.

@daniel-vacic
daniel-vacic marked this pull request as ready for review July 29, 2026 18:24

@simolus3 simolus3 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

My main concern about this is that it masks programming errors: You simply shouldn't return a connection with busy statements or in the middle of a transaction.

While this adds logs, those are still easy to ignore and this can make some errors hard to find. For example, a developer may end up wondering why changes from their transaction disappeared.

A somewhat drastic but IMO not unreasonable action might be to panic!() when a connection is dropped with busy statements or in a transaction. That also provides a backtrace pointing you straight to the source where you forgot to close a transaction or statement. What do you think?

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.

2 participants