Repository navigation
Persist pending db_version in transaction guard vtab xSync - #29
Merged
Merged
Conversation
gorbak25
added this pull request to stack #30
October 11, 2026 22:14
gorbak25
force-pushed
the
gorbak/db-version-commit-guard
branch
from
October 12, 2026 10:54
2f36bde to
d1e1900
Compare
somtochiama
approved these changes
Oct 12, 2026
Base automatically changed from
gorbak/reload-config-when-db-version-changes
to
main
October 12, 2026 15:48
gorbak25
force-pushed
the
gorbak/db-version-commit-guard
branch
from
October 12, 2026 15:48
d1e1900 to
43f698d
Compare
The first local write of a transaction enlists the crsql_version_guard virtual table; its xSync upserts the pending db_version into crsql_db_versions atomically before commit. A statement or savepoint rollback can no longer leave clocks committed under a db_version whose version marker was rolled back and later reused. A committed transaction may spend a version even when every write was rolled back to a savepoint; such gaps are harmless while reuse of a committed db_version is not. (cherry picked from commit f5db9a80, ported to V1 clock tables) Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gorbak25
force-pushed
the
gorbak/db-version-commit-guard
branch
6 times, most recently
from
October 13, 2026 10:46
3ab45d3 to
36c245e
Compare
Once crsql_version_guard is enlisted, the transaction's db_version is fixed; next_db_version and peek_next_db_version now return pendingDbVersion directly instead of re-running the max() allocation math. The un-enlisted path keeps a single fill_db_version_if_needed refresh before allocating dbVersion + 1 and enlisting. Also document that the dbVersion != -1 check in refresh_connection_state_if_needed is the first-load guard for the lazily-initialized version cache, not a data_version condition. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gorbak25
force-pushed
the
gorbak/db-version-commit-guard
branch
from
October 13, 2026 14:38
36c245e to
1b7123f
Compare
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.
A statement can be rolled back via the statement journal without rolling back the enclosing transaction:
We assign a new db_version inside triggers. If the statement is rolled back, the write of that db_version is undone too, but our in-memory state still says it was persisted, so we never write it again. After commit, a new connection sees the old db_version and reuses it. Rolled-back savepoints hit the same problem. #26 added more savepoints, which makes this the likely root cause of https://status.flyio.net/incidents/s9dzwg3d4bs7.
This PR moves db_version handling into a wrapper vtab that persists the pending db_version in its xSync callback, so it is always written at commit regardless of statement or savepoint rollbacks.
The trade-off is that transactions like this can leave gaps in db_version:
Gaps are safe, unlike reuse. If they become a problem, we can fix them by tracking savepoints properly.