Skip to content

perf(api): cache and opt in to comment reaction reads - #366

Merged
stefan-ernst merged 1 commit into
mainfrom
perf/comment-reaction-read-cache
Oct 21, 2026
Merged

stefan-ernst merged 1 commit into
mainfrom
perf/comment-reaction-read-cache

Conversation

@stefan-ernst

Copy link
Copy Markdown
Contributor

Follow-up to #364. The item view re-reads grouped reactions on every comment feed page, and the SSE reconcile re-fetches every loaded page, so a comment_reactions read rode along on each one. This cuts that read two ways.

Short-TTL cache

comment_reactions reads now consult a per-comment process cache (5s TTL, 20k entries) keyed by comment ID. AddReaction, RemoveReaction, and comment deletion invalidate the affected entry, so writes are visible immediately in the process that made them. The TTL only bounds staleness for other processes in a multi-instance deployment. Reads are already one batched IN query per page; the cache removes the repeated reads during reconcile.

Opt-in hydration

Reactions are attached only when the caller asks:

  • GET /items/{item_id}/comments?include_reactions=true
  • GET /comments/{comment_id}?include_reactions=true
  • PATCH /comments/{comment_id}?include_reactions=true
  • POST /comments/batch with "include_reactions": true

The comment UI opts in on its feed calls. Other consumers (the item-split dialog, API clients that do not render chips, the board batch path) no longer pay for the read. Default behaviour is now "no reactions in the payload".

api/openapi-v2.json and internal/restapi/v2/contract-metadata.json were regenerated.

Test plan:

  • go build ./..., gofmt, golangci-lint run on internal/services and internal/restapi/v2.
  • OpenAPI v2 metadata/generate/parity checks and the frontend v2 field guard.
  • Frontend i18n, design-token, shortcut, HMR, and svelte-check guards; Biome on the changed non-Svelte file.
  • Go: -run 'TestCommentReaction|TestV2CommentReactions' on SQLite and PostgreSQL, plus the full internal/restapi/v2 package and the Comment suite in tests/.
  • Frontend: src/lib/api/ (29 files, 467 tests) and the comments/reactions component tests.

Companion test PR: Windshiftapp/core-tests-internal#5.

The item view re-reads grouped reactions on every comment feed page, and the
SSE reconcile re-fetches every loaded page, so a comment table read rode
along on each one. Serve grouped reactions from a short-TTL process cache
invalidated by reaction writes and comment deletes, and make hydration
opt-in so feeds that never render chips skip the read entirely.

- comment_reactions reads now consult a per-comment cache (5s TTL, bounded
  entries). AddReaction, RemoveReaction, and comment deletion invalidate the
  entry; the TTL only bounds staleness across processes.
- GET /items/{item_id}/comments, GET /comments/{comment_id}, and
  PATCH /comments/{comment_id} attach reactions only when include_reactions
  is true; POST /comments/batch takes the same opt-in field. The comment UI
  opts in; other consumers no longer pay for it.
@github-actions

Copy link
Copy Markdown

Size Change: 0 B 🆕

Total Size: 0 B

compressed-size-action

@stefan-ernst
stefan-ernst merged commit 8ba64de into main Oct 21, 2026
21 checks passed
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