perf(feed): batch engagement for anon viewers too (R2 from #341)#357
Merged
spe1020 merged 2 commits intozapcooking:mainfrom Apr 26, 2026
Merged
perf(feed): batch engagement for anon viewers too (R2 from #341)#357spe1020 merged 2 commits intozapcooking:mainfrom
spe1020 merged 2 commits intozapcooking:mainfrom
Conversation
Closes the last open recommendation from the perf review docs in PR zapcooking#341 (R1 / R4 already shipped via zapcooking#344 and zapcooking#342). The batch helper itself is wired in at two sites — the rendered-events preload and the visibility-update reactive — but both gate on `$userPublickey`, which means signed-in users get batched fetches while anonymous viewers fall back to the full per-card fan-out: NoteTotalLikes → fetchEngagement(eventId) NoteTotalComments → fetchEngagement(eventId) NoteRepost → fetchEngagement(eventId) NoteTotalZaps → fetchEngagement(eventId) ReactionPills → fetchEngagement(eventId) That's up to 5× the active subscription churn per card, multiplied across a 30-event feed window, on every cold paint and every newly- rendered card. The gate isn't doing anything useful: `batchFetchEngagement`'s server-counts API doesn't require auth, and the NDK fallback subscription only uses `userPublickey` to flag userReacted / userReposted — which already correctly stay false for anonymous users either way. The per-card children themselves don't gate on sign-in; only the batch did. Drop the gate on both reactives so anonymous viewers get the same batched preload + visibility refresh signed-in users already benefit from. The 5-minute freshness gate inside batchFetchEngagement preempts the subsequent per-card fetches just like it does for the signed-in path. No behavior change for signed-in viewers (gate was always passing for them). Anonymous viewers see fewer concurrent NDK subs during feed scroll. Counts and groups continue to populate identically; no impact to the count-correctness work in zapcooking#321/zapcooking#323. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Enables the existing engagement batching path in FoodstrFeedOptimized.svelte for anonymous viewers (not just logged-in users), aligning anonymous feed behavior with the signed-in performance path and reducing per-card engagement fetch fan-out.
Changes:
- Remove
$userPublickeygating from the engagement preload and visibility-driven batch fetch reactive blocks. - Add inline comments documenting why batching should run for anonymous viewers.
- Bump
package.jsonversion from4.2.310to4.2.311.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/components/FoodstrFeedOptimized.svelte | Runs batched engagement fetching for both anonymous and signed-in viewers; adds rationale comments. |
| package.json | Patch version bump for the release containing the feed perf change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
4850
to
4852
| let lastBatchedIds = new Set<string>(); | ||
| let engagementPreloadTimeout: ReturnType<typeof setTimeout> | null = null; | ||
|
|
Contributor
Author
There was a problem hiding this comment.
@copilot apply changes based on this feedback
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the last outstanding Stage-2 recommendation from the perf review in #341. R1 (feed remount → prop-driven mode) shipped as #344 and R4 (ReactionPills key) shipped as #342; this PR finishes the trio with R2.
Problem
`FoodstrFeedOptimized.svelte` already imports and calls `batchFetchEngagement` at two sites — a rendered-near-viewport preload and a visibility-update reactive. Both gate on `$userPublickey`, so:
For each rendered note, the per-card fan-out is up to 5×:
Multiply by a 30-event feed window on every cold paint and every newly-rendered card. The cache singleton dedups the actual network query, but the active-subscription counter still climbs.
Why the gate isn't load-bearing
Fix
Drop the `$userPublickey` check from both reactive blocks. Same code path runs for signed-in and anonymous viewers; signed-in behavior is unchanged because the gate was always passing for them.
```diff
```
Comments inline document the reasoning so the next reader doesn't re-add the gate.
Risk
Test plan
🤖 Generated with Claude Code