Reduce archived conversation disk usage with cold storage#4016
Reduce archived conversation disk usage with cold storage#4016Quicksaver wants to merge 11 commits into
Conversation
- Preserve binary SQL values across archive round trips - Keep cold bundles authoritative until attachments restore safely - Bound restore memory and tolerate compatible schema changes
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a substantial new cold storage feature for archived conversations, including ~830 lines of new service code, database migrations, compression logic, and integration into the orchestration engine's dispatch flow. The scope and complexity of data lifecycle changes warrant human review. You can customize Macroscope's approvability policy. Learn more. |
- Serialize archive-tree lifecycle and recheck archived shells - Restore cleanup-pending bundles before unarchive commits - Preserve retry state for writer and filesystem failures
There was a problem hiding this comment.
One Effect service convention issue found in the new ThreadColdStorage service. See the inline comment.
Posted via Macroscope — Effect Service Conventions
- Reference-count archive-tree lock users and waiters - Remove lock entries after the final operation releases them
- Define the service members inline with Context.Service - Use the inferred Service type in the layer and orchestration test
- Match archived attachments by exact persisted ids - Resume cleanup pending manifests without shell rows - Preserve attachment metadata until durable delete cleanup succeeds
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a42fe41. Configure here.
- Reuse archive filtering for project rows and navigation - Cover persisted and optimistic archive visibility

Summary
This adds compressed cold storage for archived conversations. Once a thread is archived, its conversation data and attachments are moved out of the hot state database into a dedicated
archive.sqlitebundle, while unarchiving restores the complete thread tree before applying the domain command.The lifecycle is durable and restart-safe: migrations 035/036 queue existing archived and deleted threads, background work resumes interrupted archive/delete jobs, and restoration keeps the cold bundle authoritative until the unarchive command commits successfully. Attachment ownership is preserved from exact persisted IDs and cold-bundle filenames throughout archive, restore, and durable deletion.
What Changed
archive.sqlite.cleanup_pendingbundles, and prevented queued archive work or post-commit failures from undoing a successful restore.cleanup_pendingmanifests even when the archived shell row is missing, while preserving exact attachment metadata until durable delete cleanup succeeds.Why
With fairly moderate usage, the user
.t3folder grew to more than 30 GB. That is far too much local data growth for normal use, and without lifecycle controls it gets out of hand very quickly. Archived and deleted conversations need to stop accumulating indefinitely in hot storage while remaining reliably recoverable when a user unarchives them.Validation
pnpm exec vp checkpassed with exit 0; it reported 9 pre-existing lint warnings outside the changed files.pnpm exec vp run typecheckpassed with exit 0.pnpm exec vp run lint:mobilepassed with exit 0; optional SwiftLint, ktlint, and detekt checks were skipped because those tools are not installed locally.pnpm exec vp test apps/server/src/orchestration/Layers/ThreadColdStorage.test.ts apps/server/src/orchestration/Layers/ThreadDeletionReactor.test.ts apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts apps/server/src/persistence/Migrations/035_036_ThreadStorageLifecycle.test.tspassed: 4 files, 31 tests.pnpm exec vp test apps/web/src/components/Sidebar.logic.test.tspassed: 1 file, 58 tests.No threads yet.Proof
No attached visual proof is necessary; the data lifecycle and sidebar interaction are covered by the automated and isolated Playwright validation above.
Note
High Risk
Large new data-lifecycle path on the critical unarchive dispatch path; destructive archive/delete and filesystem I/O can corrupt or lose conversation data if rollback or queue recovery fails.
Overview
Adds gzip-compressed cold storage for archived conversations: thread-scoped SQL rows and attachments move into
archive.sqlite, hot rows/attachments/provider logs are removed, and migrations queue legacy archived/deleted threads for background work.Unarchive restores the cold bundle before the domain command commits; failed dispatches roll back the restore, and successful commits finalize by dropping the cold bundle. The lifecycle reactor now handles archive as well as delete, with startup replay of pending jobs and one-time legacy DB compaction.
Web and mobile get optimistic sidebar hide on archive and in-progress unarchive (spinners, disabled swipe/actions).
unarchiveThreadis nowasyncon mobile so the route can track loading state.Reviewed by Cursor Bugbot for commit a42fe41. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Reduce archived conversation disk usage by introducing cold storage archival and restore
ThreadColdStorageservice (ThreadColdStorage.ts) that compresses and archives thread SQLite rows to a separatearchive.sqlitedatabase on thread archive, and restores them on unarchive.ThreadDeletionReactorto handle archive, delete, and legacy-compaction lifecycle jobs, resuming pending work on startup via two new migrations (035thread_archive_manifests, 036thread_cleanup_queue).OrchestrationEnginenow callsrestoreTreebefore committing athread.unarchivecommand, rolling back on dispatch failure and finalizing on success.Macroscope summarized 1ace10b.