fix(app): eliminate persistence write amplification - #40197
Closed
Hona wants to merge 2 commits into
Closed
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR reworks app/desktop persistence to reduce write amplification by introducing a checkpointed repository abstraction and migrating prompt attachments from inline data: URLs to content-addressed blob references that are persisted durably (SQLite WAL on desktop, IndexedDB in browsers).
Changes:
- Introduces a
Repository/DurableRepositorylayer with a 500ms checkpoint controller to coalesce frequent writes. - Migrates prompt attachment handling to persist blobs by digest and render previews via object URLs, materializing
data:only at the existing submission boundary. - Adds desktop SQLite persistence + IPC API, including renderer drain coordination during shutdown and before updater installs.
Reviewed changes
Copilot reviewed 50 out of 51 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/session-ui/src/v2/components/prompt-input/types.ts | Adds blob reference type; replaces attachment dataUrl with blob. |
| packages/session-ui/src/v2/components/prompt-input/store.test.ts | Updates V2 store tests for blob-backed attachments. |
| packages/session-ui/src/v2/components/prompt-input/prompt-input.stories.tsx | Updates stories to use blob references. |
| packages/session-ui/src/v2/components/prompt-input/interaction.ts | Threads preview URLs + revocation through controller API. |
| packages/session-ui/src/v2/components/prompt-input/index.tsx | Renders attachment thumbnails via previewUrl callback. |
| packages/session-ui/src/v2/components/prompt-input/attachments.ts | Implements blob persistence, preview caching, and legacy data URL migration. |
| packages/desktop/src/renderer/index.tsx | Replaces async storage with repository-backed persistence + drain requests. |
| packages/desktop/src/renderer/i18n/index.ts | Reads locale from new persistence API. |
| packages/desktop/src/preload/types.ts | Defines PersistenceAPI and removes old store API types. |
| packages/desktop/src/preload/index.ts | Wires persistence IPC calls and drain request subscription. |
| packages/desktop/src/main/updater.ts | Drains persistence before quitAndInstall. |
| packages/desktop/src/main/updater-controller.ts | Allows async quitAndInstall and awaits it. |
| packages/desktop/src/main/persistence.ts | Adds SQLite WAL persistence for documents + content-addressed blobs, with migration. |
| packages/desktop/src/main/persistence.test.ts | Tests documents, blob integrity checks, and Electron store import. |
| packages/desktop/src/main/ipc.ts | Adds persistence IPC handlers + renderer drain coordination. |
| packages/desktop/src/main/index.ts | Initializes persistence, imports legacy stores, drains on quit/relaunch/update. |
| packages/desktop/package.json | Removes @solid-primitives/storage dependency. |
| packages/app/test-browser/review-panel-v2-state.test.ts | Updates platform mocking to use repository persistence. |
| packages/app/test-browser/prompt-persistence.test.ts | Updates persistence tests to use repository abstraction. |
| packages/app/test-browser/prompt-attachments.test.ts | Adds regression coverage for blob-backed attachments and preview stability. |
| packages/app/src/utils/prompt.ts | Adds opencode-blob: URLs + restore path for historical data: attachments. |
| packages/app/src/utils/prompt.test.ts | Updates prompt extraction tests and adds restore coverage. |
| packages/app/src/utils/persist.ts | Replaces makePersisted with repository-backed persistence + legacy migrations. |
| packages/app/src/utils/persist.test.ts | Refocuses tests on address/normalization semantics. |
| packages/app/src/persistence/repository.ts | Adds checkpointed repository wrapper over durable backends. |
| packages/app/src/persistence/repository.test.ts | Tests repository coalescing at checkpoint deadline. |
| packages/app/src/persistence/indexed-db.ts | Implements IndexedDB durable repository for browsers + blob integrity checks. |
| packages/app/src/persistence/index.ts | Exports persistence primitives. |
| packages/app/src/persistence/checkpoint.ts | Adds 500ms checkpoint controller implementation. |
| packages/app/src/persistence/checkpoint.test.ts | Tests checkpoint scheduling, coalescing, drain semantics, retry-on-drain. |
| packages/app/src/pages/session/use-session-commands.tsx | Restores prompts using blob persistence when reverting. |
| packages/app/src/pages/session.tsx | Restores drafts via blob persistence; reads blobs when needed. |
| packages/app/src/index.ts | Exports repository APIs from app package for desktop integration. |
| packages/app/src/context/server-session.ts | Adds optimistic cleanup hook for attachment/object URL lifecycle. |
| packages/app/src/context/server-session.test.ts | Adds cleanup assertions and attachment URL confirmation coverage. |
| packages/app/src/context/prompt-state.ts | Migrates image parts to blob references and deep clones blob refs. |
| packages/app/src/context/platform.tsx | Replaces storage with persistence, defaulting to IndexedDB repo. |
| packages/app/src/context/directory-sync.ts | Threads optimistic cleanup capability through directory sync. |
| packages/app/src/components/prompt-input/submit.ts | Resolves blob refs to canonical data: at submission; optimistic object URLs + cleanup. |
| packages/app/src/components/prompt-input/submit.test.ts | Adds submission coverage for blob ref resolution and command attachments. |
| packages/app/src/components/prompt-input/image-attachments.tsx | Renders thumbnails via preview callback. |
| packages/app/src/components/prompt-input/history.ts | Deep clones blob references for history navigation. |
| packages/app/src/components/prompt-input/history.test.ts | Updates history tests for blob ref cloning. |
| packages/app/src/components/prompt-input/build-request-parts.ts | Uses opencode-blob: URL placeholders for attachments. |
| packages/app/src/components/prompt-input/build-request-parts.test.ts | Updates tests for new attachment URL scheme. |
| packages/app/src/components/prompt-input/attachments.ts | Blob-backed attachment persistence + preview cache + legacy migration. |
| packages/app/src/components/prompt-input.tsx | Integrates blob persistence into PromptInput v1 attachments and previewing. |
| packages/app/src/components/prompt-input-v2.tsx | Integrates blob persistence into PromptInput v2. |
| packages/app/src/components/dialog-fork.tsx | Restores fork prompts via blob persistence before navigation. |
| packages/app/package.json | Removes @solid-primitives/storage dependency. |
| bun.lock | Removes @solid-primitives/storage and updates patched/trusted ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+283
to
+288
| const persistence = platform?.persistence ?? getIndexedDBRepository() | ||
| return Promise.all([ | ||
| persistence.remove(address(config)), | ||
| ...(config.legacyStorageNames ?? []).map((storage) => persistence.remove({ storage, key: config.key })), | ||
| ...(config.legacy ?? []).map((key) => persistence.remove({ storage: LEGACY_STORAGE, key })), | ||
| ]).then(() => undefined) |
Comment on lines
+58
to
+65
| (error) => { | ||
| inFlight = false | ||
| idleWaiters.splice(0).forEach((resolve) => resolve()) | ||
| dirtySince = Math.min(attemptedSince ?? Date.now(), dirtySince ?? Number.POSITIVE_INFINITY) | ||
| const pending = waiters | ||
| waiters = [] | ||
| pending.forEach((waiter) => waiter.reject(error)) | ||
| }, |
Member
Author
|
Superseded by the narrower draft-only implementation in #40207. |
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.
Summary
makePersistedwrites with a shared repository and fixed 500ms checkpoint deadlineVerification