Establishes version control for the personal Logseq DB fork before starting the server-client architecture migration and domain features described in docs/agent-guide and the approved implementation plan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
118 lines
5.3 KiB
Markdown
118 lines
5.3 KiB
Markdown
# ADR 0022: Remove the UI DataScript DB and Refactor Editor First
|
|
|
|
Date: 2026-07-08
|
|
Status: Accepted
|
|
|
|
## Context
|
|
|
|
The db worker is the durable owner of graph data, but the renderer has still
|
|
kept a second DataScript connection as a UI read model. That split makes graph
|
|
reads harder to reason about because UI code can read stale renderer entities,
|
|
perform reverse lookups locally, or depend on lazy entity navigation that does
|
|
not exist when the worker database is the only graph database.
|
|
|
|
The renderer has used this UI DB through several shapes:
|
|
|
|
- direct `d/entity`, `d/pull`, `d/q`, `db/entity`, `db/pull`, and
|
|
`db-model/*` calls;
|
|
- reverse lookup attributes such as `:block/_alias` and `:block/_refs`;
|
|
- nested entity or pull-map reads such as reading fields from
|
|
`(:block/parent block)`;
|
|
- handler code that performs graph-backed editor calculations before
|
|
dispatching worker transactions.
|
|
|
|
The editor is the highest-risk migration surface because it combines block
|
|
tree reads, sibling and parent selection, paste, delete, merge, quick-add,
|
|
navigation, undo metadata, DOM focus, and outliner transactions. Removing the
|
|
UI DB without simplifying editor ownership would preserve the same complexity
|
|
behind async worker calls.
|
|
|
|
## Decision
|
|
|
|
Remove the renderer-owned DataScript database as a graph read model.
|
|
|
|
The db worker is the only owner of graph facts. UI code must not depend on
|
|
DataScript entities, lazy entity navigation, reverse lookup attributes, or
|
|
renderer-side pull maps for graph computation.
|
|
|
|
Refactor editor ownership first:
|
|
|
|
1. Move graph-backed editor calculations to worker APIs.
|
|
2. Add worker editor namespaces where editor-specific graph operations need a
|
|
clear home.
|
|
3. Keep UI editor handlers thin: they dispatch user intent, coordinate DOM and
|
|
focus state, and consume explicit worker payloads.
|
|
4. Return plain data from worker APIs with explicit fields needed by the UI.
|
|
Do not rely on entity identity, lazy nested refs, or reverse attributes.
|
|
5. Keep components focused on rendering and event dispatch. Component
|
|
migration comes after handler/editor contracts are explicit.
|
|
|
|
Do not add a renderer cache to replace the UI DB. If a cache becomes necessary,
|
|
it must have a narrowly documented owner, invalidation rule, and test case.
|
|
The default design is no cache.
|
|
|
|
Do not keep a compatibility layer that lets UI code continue to call
|
|
renderer-style DB helpers. Compatibility wrappers may remain only while their
|
|
call sites are being removed, and they must not hide a second graph database.
|
|
|
|
## Migration Shape
|
|
|
|
1. Add guard tests that count and reject direct UI DB reads, reverse lookups,
|
|
and nested entity or pull-map assumptions in frontend UI code.
|
|
2. Remove direct `d/entity`, `d/pull`, `d/q`, `db/entity`, `db/pull`,
|
|
`db-model/*`, and renderer `conn/get-db` reads from handlers and events.
|
|
3. Move editor calculations to worker APIs before converting component-heavy
|
|
surfaces.
|
|
4. Replace reverse lookup usage with worker-owned queries that return explicit
|
|
result fields.
|
|
5. Replace nested entity reads with explicit worker payloads, for example
|
|
parent ids, page ids, children, aliases, refs, or sibling blocks.
|
|
6. Keep outliner writes on worker-backed transaction paths and keep UI code
|
|
out of DB transaction assembly when the worker can own the calculation.
|
|
7. Convert components last so they render worker-shaped data and dispatch UI
|
|
events without graph reads.
|
|
8. Run focused tests after each migration batch, then run the broader test and
|
|
e2e suites when the UI DB removal is complete.
|
|
|
|
## Consequences
|
|
|
|
UI code becomes more explicit. It must ask the worker for the graph data or
|
|
editor decision it needs instead of navigating a local entity graph.
|
|
|
|
Worker APIs increase during the migration, especially around editor behavior.
|
|
That is intentional when the API represents a real graph-backed editor
|
|
operation. APIs should stay narrow and return plain data.
|
|
|
|
Editor behavior needs stronger focused coverage because many previously local
|
|
reads become async worker calls. Tests should cover insert, delete, merge,
|
|
paste, quick-add, sibling navigation, focused-root behavior, and reverse lookup
|
|
replacement paths.
|
|
|
|
Component migration is delayed until handler and editor worker contracts are
|
|
stable. This keeps rendering code simpler and avoids moving complex graph
|
|
calculation into components.
|
|
|
|
The removal may temporarily leave old helper namespaces in place while call
|
|
sites are drained, but the target architecture has no renderer-owned graph DB.
|
|
|
|
## Rejected Alternatives
|
|
|
|
### Keep a Renderer Read Cache
|
|
|
|
A renderer cache would preserve much of the old split-brain behavior and would
|
|
need invalidation logic for every worker transaction, sync update, import,
|
|
undo, redo, and rebase path. That adds complexity without solving ownership.
|
|
|
|
### Convert Components Before Editor
|
|
|
|
Component-first migration would move the easiest render reads first while
|
|
leaving the most complex graph-backed behavior in handlers. Editor behavior
|
|
would continue to depend on old assumptions, and later changes would force a
|
|
second pass through component contracts.
|
|
|
|
### Preserve Entity-shaped Worker Results
|
|
|
|
Returning entity-like maps with nested refs would keep the renderer coupled to
|
|
DataScript navigation semantics. Explicit worker payloads are easier to test,
|
|
serialize, and reason about across thread boundaries.
|