Skip to content

feat(revisions): retain history with expiring undo records - #24

Merged
hden merged 2 commits into
mainfrom
feat/revision-undo-retention
Oct 22, 2026
Merged

hden merged 2 commits into
mainfrom
feat/revision-undo-retention

Conversation

@hden

@hden hden commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Revision history used forward page deltas, so retaining a revision could require ancestors outside the retention window. Store encrypted undo records instead and let SlateDB TTL and compaction reclaim expired history.

HEAD now contains its own page count, and HEAD/current pages explicitly have no expiry. Publication captures before-images, the parent descriptor, current pages, and HEAD in one transaction and awaits durability. A state remains recoverable for the configured period after it is replaced, including after long inactivity.

  • Add REVISION_RETENTION_DAYS (default: 30), preserving expiry order when retention is shortened.
  • Restore historical states by applying newer undo records, including SQLite shrink/regrowth and repeated page updates.
  • Bootstrap expired client cursors with all selected target pages; preserve explicit server revisions and surface corrupt or missing unexpired history.

The persisted HEAD/revision format is intentionally incompatible; no migration is included for this pre-release application.

Validation:

  • docker compose run --rm --no-deps app bb verify: 225 tests, 1,032 assertions, no failures; lint, source loading, and formatting passed.
  • SDK 0.8.3 HTTP E2E: clojure -M:e2e passed.
  • Native compaction removes expired history while preserving current and retained values. Tests also cover history-free reads/writes, rollback/retry, retention shortening, SQLite shrink/regrowth, and cross-vault recovery.

Synthetic memory-store measurement (128 × 4 KiB pages, 8 changed pages per revision, 110 revisions): p95 publish 107 ms including durability wait; HEAD read 1.6 ms; previous-revision read 1.5 ms; root read through 110 undo records 25 ms. These are local measurements, not production performance guarantees.

hden added 2 commits October 23, 2026 00:05
Forward page deltas depend on ancestors beyond the retention window.
Capture before-images with their parent state in the publish transaction so
SlateDB TTL and compaction can reclaim history independently.

Keep HEAD and current pages without expiry so inactivity never removes the
current database. Retain replaced states for 30 configurable days, preserve
expiry ordering when retention is shortened, and bootstrap expired client
cursors against the selected target.

BREAKING CHANGE: HEAD and stored revisions use a new format. No migration
is provided because the application has not been released.
A cursor spanning page growth followed by shrinkage can include removed
tail pages in its change set. Reading those pages produces nil values that
cannot be serialized by the protobuf pull stream.

Bound selected page IDs to the target snapshot size before fetching them.
Cover page selectors, empty targets, and historical targets after HEAD has
regrown, including the real SlateDB-to-protobuf streaming path.
@hden
hden merged commit 918f72f into main Oct 22, 2026
1 check passed
@hden
hden deleted the feat/revision-undo-retention branch October 22, 2026 23:36
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.79412% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.22%. Comparing base (a4ce78e) to head (d7173e6).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/linear/adapter/slatedb/store.clj 90.90% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #24      +/-   ##
==========================================
+ Coverage   92.96%   93.22%   +0.26%     
==========================================
  Files          48       48              
  Lines        3296     3321      +25     
==========================================
+ Hits         3064     3096      +32     
+ Misses        232      225       -7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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