Skip to content

refactor(web): extract collab-flush path from item-detail monolith (TASK-2082)#889

Merged
xarmian merged 2 commits into
mainfrom
refactor/task-2082-extract-collab-flush
Jul 10, 2026
Merged

refactor(web): extract collab-flush path from item-detail monolith (TASK-2082)#889
xarmian merged 2 commits into
mainfrom
refactor/task-2082-extract-collab-flush

Conversation

@xarmian

@xarmian xarmian commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Behavior-preserving extraction of the Yjs collaborative-snapshot flush path out of the ~4.6k-line item detail page (web/src/routes/[username]/[workspace]/[collection]/[slug]/+page.svelte) into a new focused module. Follow-on to TASK-2029 (which extracted the raw-markdown contentSaver), part of PLAN-1984.

Extracted — web/src/lib/collab/collabFlush.svelte.ts

A createCollabFlusher() factory (mirrors contentSaver.svelte.ts's pattern). The module owns: the 5s idle debounce timer, the per-item lastFlushedContent dedupe state, and the two-stage dedupe decision (editor-space short-circuit via shouldDedupeEditorSpace + storage-space baseline/lastFlushed compare). Public API:

  • schedule(ctx, markdown) — arm the 5s idle flush (was scheduleCollabFlush)
  • flush(ctx, markdown, keepalive) — run a flush now, returns 'flushed'|'deduped'|'failed'|'skipped' (was runCollabFlush; called directly by the rich→raw toggle)
  • flushNow(ctx, keepalive) — read live editor markdown + flush (was flushCollabNow; editor teardown + beforeunload)
  • cancel() / resetDedup() — replace the inline clearTimeout(collabFlushTimer) / lastFlushedContent = null sites

Deliberately LEFT in the page (injected as callbacks)

Everything Svelte-reactive / API / editor-coupled the module can't own: the api.items.flushCollabContent PATCH + all reactive bookkeeping (saveStatus, editorStore, toast, showSaved), the op-log-cursor read + post-await force_refresh check (in save), plus isRecovering (forceRefreshInFlight), serialize (markdownToWikiLinks/cleanBrokenLinks against localIndex), normalize (unescapeDocLinks), readEditorMarkdown, isActiveItem. activeCollabContext / seededProvider / the collab $effect lifecycle stay in the page — they're deeply coupled to provider construction/teardown.

Behavior-preserving

Line-for-line faithful to the original control flow. Verified invariants:

  • beforeunload: collab flushNow(ctx, true) still fires ALONGSIDE the BUG-2024 raw-markdown keepalive PATCH (both intact, unchanged ordering).
  • forceRefreshInFlight gating (schedule + pre/post-await), seededProvider seeding, activeCollabContext switch-on-item-change all unchanged.
  • Flush debounce timing (5s) + dedup (editor-space + storage-space) unchanged; flushDedupe.ts reused as-is.
  • Item-swap resets cancel the pending flush (cancel() + resetDedup() in loadData) — no cross-item bleed.

One robustness addition from Codex review: a resetGeneration guard so an in-flight resetDedup() (item-swap / out-of-band raw save) can't be re-polluted by a stale flush's deferred lastFlushedContent commit — closes a window the await config.save() split would otherwise widen, and strengthens the same-item raw-save case that was latently racy in the original.

Line-count delta

Item page: 4649 → 4558 lines (−91). Net across files: +625 / −231 (new module + its unit tests).

Tests

New web/src/lib/collab/collabFlush.test.ts (17 tests, node project): debounce/coalesce, recovery gate, editor-space + storage-space + baseline dedupe, lastFlushed recording + active-item gate, failed/skipped non-recording, flushNow read/no-op/cancel, resetDedup, and the in-flight-reset invalidation. npm run check clean (0 errors), npm run build succeeds, all 177 node tests pass. Codex review: CLEAN.

Refs TASK-2082, PLAN-1984.

@xarmian xarmian merged commit be8fdf8 into main Jul 10, 2026
3 of 4 checks passed
@xarmian xarmian deleted the refactor/task-2082-extract-collab-flush branch July 10, 2026 00:27
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.

1 participant