Skip to content

fix(feed): keep sorted pagination advancing - #548

Merged
NotThatKindOfDrLiz merged 5 commits into
mainfrom
fix/sorted-feed-raw-pagination
Aug 12, 2026
Merged

fix(feed): keep sorted pagination advancing#548
NotThatKindOfDrLiz merged 5 commits into
mainfrom
fix/sorted-feed-raw-pagination

Conversation

@NotThatKindOfDrLiz

@NotThatKindOfDrLiz NotThatKindOfDrLiz commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Advance sorted websocket fallback feeds by raw relay event windows instead of parsed video count.
  • Backfill bounded zero-parse relay pages so infinite scroll does not receive an empty live page.
  • Keep VideoFeed infinite scroll keyed to unfiltered fetched count so dedupe, mute filtering, or verified-only filtering cannot leave react-infinite-scroll-component latched.
  • Add focused regression coverage for sorted short parses, disjoint raw windows, zero-parse backfill, raw exhaustion, chronological zero-parse cursor advancement, filtered VideoFeed scroll re-arming, and page-window Classic sorting.

Motivation

  • Sorted fallback pagination could stop permanently when the relay returned a full raw page but parsing dropped one or more events.
  • The same raw/parsed unit mismatch could also overlap later sorted pages because the hook sliced a re-sorted parsed prefix.
  • VideoFeed could still preserve the user-visible stall after downstream filtering because its dataLength was the rendered filtered count rather than the fetched count.

Behavior Notes

  • Sorted websocket fallback still uses growing raw prefixes because NIP-50 has no offset parameter.
  • Client-side Classic and hashtag sorting now applies to the current raw page window after slicing, not to the full parsed prefix. That avoids cross-page overlap at the cost of global client-side ordering across page boundaries.

Related Issue

Testing

  • npm run test
  • Manual verification completed

Visuals

  • UI change with screenshots/video attached
  • No visual change
  • Visuals and text avoid sensitive external brand or partner names unless explicitly approved

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 9, 2026

Copy link
Copy Markdown

Deploying divine-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1b14ed0
Status: ✅  Deploy successful!
Preview URL: https://197eac50.divine-web.pages.dev
Branch Preview URL: https://fix-sorted-feed-raw-paginati.divine-web.pages.dev

View logs

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

🚀 Preview Deployment

Last updated: 2026-08-12T01:30:06.484Z

Property Value
Preview URL https://a96fbe38.divine-web-fm8.pages.dev
Commit 1b14ed0
Branch fix/sorted-feed-raw-pagination
Workflow run #1094

@NotThatKindOfDrLiz
NotThatKindOfDrLiz requested review from a team and mbradley and removed request for a team August 12, 2026 00:10
@NotThatKindOfDrLiz

Copy link
Copy Markdown
Member Author

@rabble @mbradley quick nudge for review when you have a chance. Follow-up commit is pushed, PR body is updated, and all checks are green. The remaining gate is human review.

RAW_FEED_BACKFILL_ATTEMPTS bounds the zero-parse retry loop, but it also
silently bounds how deep a feed can reach: after ~cap*pageSize consecutive
unparseable events, pagination stops even if valid videos exist deeper. The
PR body documents the relay-limit stop but not this one. Note the tradeoff so
the cap is not later raised or removed without weighing the loop risk.
The raw-event timestamp cursor is correct only because nostr.query returns
non-search results sorted created_at desc (NPool) and video feeds bypass the
profile/contact cache. If that ordering guarantee changes, the cursor would
skip events and silently drop videos from the feed. Record the dependency at
the point that depends on it.

@mbradley mbradley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the pagination rework (base head e21bef5). The raw-event cursor is the right fix for the parsed/raw unit mismatch: advancing sorted offsets by events consumed rather than parsed videos skips dropped events without overlap, and keying InfiniteScroll to unfiltered fetchedCount stops mute/verified-only/dedupe filtering from latching the scroller. Verified the 34 affected tests pass, mutation-checked the two core guards (they go red when the fix is reverted), and typecheck is clean.

Pushed two doc-only commits recording invariants the code leans on but did not state: the backfill cap doubles as a feed reachability ceiling, and the chronological cursor depends on NPool returning non-search results newest-first. Neither changes behavior.

One noted trade, no action needed: client-side Classic/sort:top ordering is now per-page-window rather than global on the websocket fallback. It is disclosed in the PR body and it is the right call here, since preserving global order would reintroduce the raw/parsed mismatch this PR removes.

Approving.

@mbradley mbradley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving on 1b14ed0. My earlier approval was pinned to 85c534b, before the latch-gap merge you pushed. Checked the delta: v2-cursor now stops on a zero-parse page, the search feed's scroll is keyed to raw fetched count, and the #550 featured-tab conflict resolution kept both sides (both InfiniteScroll instances key to fetchedCount). New v2 guard's test goes red when the guard is reverted, and test (20.x) is green at head. Good to merge.

@NotThatKindOfDrLiz
NotThatKindOfDrLiz merged commit c1b01ee into main Aug 12, 2026
5 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.

fix(feed): sorted-feed pagination stops permanently when a page parses short

2 participants