Skip to content

Bound database message reads with a limit and tail cursor #135

Description

@zealsprince

Database::messages() on the #34 branch (307bdcd) returns every row a channel has, and GetState calls it once per channel on every invocation. That was fine when the buffer lived in memory and died with the session; now the store persists, and rows only accumulate (every reconnect writes a fresh self-JOIN, scroll-back writes pages down). Reads that scale with lifetime channel history instead of with what the UI can show will get slower every week the client is used, and the failure is gradual enough that nobody notices until a busy channel takes seconds to open.

Give the trait a bounded read: messages() takes a limit and returns the newest N for the channel (the tail), reading the server-channel-timestamp index backwards with a cursor rather than materializing the whole range. Add a before-anchored page read for scroll-back so older history comes out in CACHE_PAGE_SIZE chunks instead of arriving implicitly via the full scan. Callers in handle_command (GetState, GetChannelState) pass a live-window-sized limit. The local-cache spec's port shape (seed, pageBefore) is the naming and semantics to converge on, so the core interface doesn't need renaming when the platform cache port lands.

Spec links:

Acceptance criteria:

  • Database::messages() (or its successor) takes a limit and returns at most that many messages, the newest for the channel, still in ascending server_time order.
  • A before-anchored read exists that returns the page of messages older than a given msgid, bounded by the same kind of limit.
  • The IndexedDB implementation serves both via index cursors and never materializes the full channel range for a bounded read.
  • GetState and GetChannelState request a bounded tail rather than the whole channel.
  • A channel with more rows than the limit opens with exactly the newest window; older pages arrive only when explicitly requested.

Out of scope: the platform-side HistoryCachePort and its adapters (epic #10, #54-#58 own that surface), retention or pruning of old rows (nothing deletes yet, and that's a separate decision), and the app-side scroll listener that triggers paging.

Blocked by #34, which introduces the Database trait and the IndexedDB store this bounds. #134 (core test harness) isn't a blocker but is where the limit and paging behaviors should get their assertions.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    clientClient apps: UI, platform adapters, cache, PWAuplinkThe IRC layer: protocol, caps, messaging, metadata

    Type

    Fields

    Size

    None yet

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions