Document persistence hooks: load, store, and content-cache refresh #35
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#35
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The collab server becomes the writer of page state: load on first open, debounced store, derived content refresh (ADR 0003).
Scope
Implement
onLoadDocument(mergeydoc_state+page_updateslog) andonStoreDocument(debounce 2 s / max 30 s: append update to log, periodically merge into state) against PostgreSQL, then refreshpage_content_cachevia the shared derivation (#23/#24) and updatepages.updated_at. Remove/disable the RESTPUT /pages/:id/statewrite path (keep read). Enforce the document size ceiling on updates.Acceptance criteria
Technical notes
page_updates), realtime-collaboration.md §lifecycle.Dependencies
Depends on #24, #34.
Size: ~2 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Verified on Test and Int (commit
7d8f331, pipeline green — all CI + CD jobs incl. Int promotion).Live end-to-end on Test: logged in as fixture-user → created a page →
GET /pages/:id/collab-token(moderw) → connected a real@hocuspocus/providerclient towss://test.dorfteich.cloud/collab→ edited the document → within the store debounce,GET /pages/:id/export/markdown(which servespage_content_cache.markdown) returned the edited text. So the collab server is persisting state and refreshing the derived cache live through the proxy. Both collab containers stayed healthy.What landed (ADR 0003, realtime-collaboration.md §lifecycle):
onLoadDocumentreconstructs a page'sY.Docfrom PostgreSQL by applyingpages.ydoc_stateand then everypage_updatesrow inseqorder.onStoreDocumentpersists debounced (2 s, max 30 s): appends the delta since the last flush topage_updates, periodically merges the log back intoydoc_state(inline threshold — the session-aware compaction of idle pages stays the separate job, #40), refreshespage_content_cache(plain/markdown/html/outline via the shared derivation, #24), bumpspages.updated_at, and keepsAttachment.pageIdpointed at the embedding page (#31). One transaction per flush; flush duration logged.MAX_PAGE_DOCUMENT_BYTES, 5 MiB) enforced on store: an oversize document is not persisted and clients are notified via a stateless error so they can revert.Tests: persistence is an injected port. A DB-backed suite covers the Postgres implementation (store/load round-trip, cache refresh, a 1000-entry update log, size-ceiling rejection, not-found) against an isolated
_collabtest database; an integration suite covers the hook wiring (two-client sync, survival across a server restart, the size-ceiling stateless notification) with an in-memory fake.Sequencing note (one acceptance box moved by design): the criterion "REST state writes now return 410" is intentionally deferred to #36. #35 keeps
PUT /pages/:id/stateworking; #36 switches the editor to the collab provider and retires the REST write path (410) in the same change, so the deployed editor is never left unable to save between the two deploys.