fix(core): gate workspace schema migrations behind PRAGMA user_version (#733) - #807
Conversation
#733) _ensure_schema_upgrades ran ~30 DDL statements plus multiple write commits on every get_workspace() call — i.e. on every authenticated v2 request. Stamp SCHEMA_VERSION into PRAGMA user_version at init and after migration; steady-state loads now return after a single pragma read (zero DDL, zero write commits, verified via PRAGMA data_version in tests).
The pre-migration tasks-table simulation left the fresh DB's schema-version stamp in place, so the now-gated migration correctly skipped. A genuine legacy DB predates the stamp; reset PRAGMA user_version = 0 to keep the simulation faithful.
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 52 minutes Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds a ChangesSchema version gating
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant get_workspace
participant EnsureSchemaUpgrades
participant SQLiteDB
Caller->>get_workspace: request workspace
get_workspace->>EnsureSchemaUpgrades: _ensure_schema_upgrades()
EnsureSchemaUpgrades->>SQLiteDB: read PRAGMA user_version
alt version >= SCHEMA_VERSION
EnsureSchemaUpgrades->>SQLiteDB: close connection
EnsureSchemaUpgrades-->>get_workspace: return early, no DDL
else version < SCHEMA_VERSION
EnsureSchemaUpgrades->>SQLiteDB: run DDL upgrades
EnsureSchemaUpgrades->>SQLiteDB: PRAGMA user_version = SCHEMA_VERSION
EnsureSchemaUpgrades-->>get_workspace: return
end
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code Review — fix(core): gate workspace schema migrations behind PRAGMA user_version (#733)Overall: This is a clean, well-scoped performance fix. The approach is correct, the PR description is thorough, and the What's working well
Issues / suggestions1. Connection leak in the early-return path ( conn = _open_db(db_path)
cursor = conn.cursor()
if cursor.execute("PRAGMA user_version").fetchone()[0] >= SCHEMA_VERSION:
conn.close() # ← fine when it runs, but…
returnIf conn = _open_db(db_path)
try:
cursor = conn.cursor()
if cursor.execute("PRAGMA user_version").fetchone()[0] >= SCHEMA_VERSION:
return
# ... all migration DDL ...
cursor.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")
conn.commit()
finally:
conn.close()This eliminates the duplicate 2. f-string for PRAGMA value cursor.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")SQLite's # PRAGMA doesn't accept ? placeholders; SCHEMA_VERSION is a module-level int constant.
cursor.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")3. The test drops 4. Concurrent first-load on an unversioned DB Acknowledged in the PR description. Two processes can race through the migration path simultaneously; since every DDL statement is Minor nit
SummaryThe fix is correct and the test suite directly proves the intended invariant. The connection-leak risk in the early-return path is the only substantive concern — worth a |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
codeframe/core/workspace.py (1)
57-61: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider a regression test asserting schema/version parity.
Nothing currently enforces that a future column/table addition to
_init_database/_ensure_schema_upgradesis paired with aSCHEMA_VERSIONbump — relies entirely on the comment convention. A test that hashes/inspects the full schema and compares it against a recordedSCHEMA_VERSION-keyed fixture would catch drift early, but this is speculative hardening beyond the current fix.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@codeframe/core/workspace.py` around lines 57 - 61, Add a regression test for schema/version parity around SCHEMA_VERSION in workspace.py, since the current comment-only convention can drift from _init_database and _ensure_schema_upgrades. Update the test to inspect or snapshot the full schema created by those functions and assert it matches the recorded SCHEMA_VERSION fixture, so any future table/column/index change in Workspace initialization or migration paths requires a corresponding version bump.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@codeframe/core/workspace.py`:
- Around line 57-61: Add a regression test for schema/version parity around
SCHEMA_VERSION in workspace.py, since the current comment-only convention can
drift from _init_database and _ensure_schema_upgrades. Update the test to
inspect or snapshot the full schema created by those functions and assert it
matches the recorded SCHEMA_VERSION fixture, so any future table/column/index
change in Workspace initialization or migration paths requires a corresponding
version bump.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d9491a2c-df67-4fd4-bab0-2d2d4d3ddaf4
📒 Files selected for processing (3)
codeframe/core/workspace.pytests/core/test_task_requirement_ids.pytests/core/test_workspace.py
…comments, constant placement - Close the connection if the user_version probe itself raises (claude-review) - Note why the PRAGMA stamp is an f-string (no ? placeholder support) - Group SCHEMA_VERSION with the other module constants
|
Review feedback triage (commit 3a5dd3d):
|
Follow-up Review — commit 3a5dd3dAll three substantive items from my first review are addressed. Confirming: ✅ Connection leak (#1): The early-return path now wraps the ✅ f-string PRAGMA comments (#2): Both stamp sites in ✅ Constant placement (nit): The two non-blocking points (#3 test scope, #4 concurrent first-load) were correctly left as-is per the original review. This PR is ready to merge. The fix is correct, minimal, and directly proven by the |
Summary
Fixes #733 —
get_workspace()ran_ensure_schema_upgrades()(~30 DDL statements + multiple write commits, each an fsync in WAL) on every call, i.e. on every authenticated v2 request viaget_v2_workspace.SCHEMA_VERSION = 1module constant, stamped intoPRAGMA user_versionby_init_databaseand after a completed migration run._ensure_schema_upgrades()now returns after a singlePRAGMA user_versionread when the DB is current — zero DDL, zero write commits.user_version = 0) run the unchanged, idempotent migration path exactly once, then get stamped._init_database/_ensure_schema_upgradesgain a migration.Acceptance criteria (from issue)
PRAGMA user_versioncheckPRAGMA data_version(unchanged across repeatedget_workspace()calls) from an independent connectionTests
TestSchemaVersionGate: fresh-workspace stamp, steady-state zero-writes (viadata_version), legacy-DB migration + re-stamp.test_task_without_requirement_ids_in_existing_db: its legacy-schema simulation now also resetsuser_version = 0, as a genuine pre-migration DB would have.ruffclean. Cross-familycodex review: no findings.Known limitations
SCHEMA_VERSIONwhen adding a migration would skip it on existing DBs; the bump rule is documented at the constant and at both stamp sites.Summary by CodeRabbit
Bug Fixes
Tests