Repository navigation
Paginate Timeline by 30 roots and reconcile cross-page moves - #117
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee92650611
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let epoch = t.next_request in | ||
| Hashtbl.replace t.root_page_epochs page.id epoch; |
There was a problem hiding this comment.
Keep feed scans from cancelling full-page reconciliation
Inferred from the resync path: rehydrate_current_interests starts both a prefix feed scan and read_changed_roots for retained pages, but both owners overwrite this same page epoch. If the journal-list response starts the feed's root read while the changed-page read is still collecting previews or subsequent batches, its remaining completions are discarded by root_batch_current, and superseded_root_batch silently drops Changed_roots. For a day with more than 30 loaded roots, refresh_feed then preserves the old suffix without the cancelled reconciliation updating it, leaving remote edits or deletions beyond the refreshed prefix stale. Separate the owners' epochs or coordinate these reads so the prefix refresh cannot cancel the reconciliation responsible for that suffix.
Useful? React with 👍 / 👎.
Timeline's tree-node quota could spend the display budget on children, and future journals could fill the first batch while the unread Today section appeared empty. Initial loads and every continuation now share a 30-displayed-root scanner. The first batch prioritizes Today, then fills from descending journal dates; future journals remain reachable and final display keeps date/sibling order.
Read roots at depth zero, then fetch bounded direct-child previews and display asset metadata through existing Worker commands. Headers, children and assets do not consume the root quota; resource delivery remains asynchronous. The dbworker API is unchanged. Date packets remain seven metadata entries, without a seven-date stop condition.
App-local date continuation is independent of display order. Runtime retains each page's later-date traversal separately from disposable Worker structure cursors, so stale-cursor recovery, Retry and retained-page reconciliation cannot drop deferred future/older dates. Graph reset clears it. Keep a separate date continuation visible even when authoritative deletion/reconciliation removes the day's root continuation. Sync refresh treats Today and the chronological prefix separately, preserves loaded history and UUID anchors, and removes old copies of identities moved into a fresh prefix. Page invalidation epochs allow prefix reads and retained reconciliation to complete together.
A normal cross-day move could also blank Timeline: a point read combined the returned page ID with cached old date/parent context, then a contiguous page splice could leave duplicate UUIDs in retained history. Resolve point reads against their actual page (fetching unknown page metadata through the existing API), retire superseded point/context responses (including every observation started before a resync), and relocate changed root membership/order only inside loaded ranges. Authoritative page replacement removes the whole old page and old occurrences of incoming UUIDs across pages, updates date counts and preserves unread continuations and UUID anchors. Swift duplicate rejection is unchanged; this repairs the upstream model. Several implicated methods also existed in the release baseline, so the whole failure is not attributed solely to this PR's new quota.
Validation:
Limits: 30 is a displayed-root quota, not a hard bound on DB scanning, snapshots, bytes or parsing. The pre-existing change-window pagination and older-Feed loading/error presentation issues remain outside scope. No merge, release or real-graph mutation is part of this change.