Skip to content

cache: persist folded timeline snapshots instead of a raw event log #481

Description

@gbasin

Context

The web/mobile timeline cache (shared/src/cache.ts, web/src/cacheIdb.ts) persists a raw event log per channel (CachedTimeline = { events: WireEvent[], hasMore }, max 300/channel): message.posted rows with their original text plus separate modifier events accumulated from the ack/WS path. On warm reload, mergeHistory (shared/src/timeline.ts) must re-apply those modifiers or acked edits/reactions silently vanish — this replay is the last structurally load-bearing copy of the client fold and has been the root of the warm-reload staleness family (#454, #460, #467).

Unlocked by the folded catch-up wire

Once reconnect/catch-up ships watermarked folded rows (lastModifierId on wire rows, server change-feed keyed by message_state.last_modifier_id), the cache can stop being an event log:

  • Persist folded rows only (the wire shape already IS the folded shape; cached rows carry lastModifierId).
  • Live WS modifiers update the cached row in place (or are dropped — the next delta heals) instead of appending to a replay log.
  • mergeHistory's modifier-replay path and cachedTimelineNeedsStructuralRepair retire entirely; warm reload becomes hydrate + watermark-gated delta.

Notes

  • Needs cache schema versioning (existing IndexedDB data is a raw log; simplest migration: drop and refetch on version bump).
  • Effect schemas ignore excess keys, so cached folded rows are forward/backward tolerant.
  • Deliberately split out of the folded-wire PR to keep that train reviewable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions