fix(syncer): reject non-advancing message page cursors - #192
Conversation
A full 100-message page whose last or newest ID is empty or repeats made bootstrap, forward, and unlimited backfill reprint forever. Fail closed on a stuck before/after cursor, matching GuildMembers. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs real behavior proof before merge. Reviewed August 31, 2026, 12:00 AM ET / 04:00 UTC. ClawSweeper reviewWhat this changesThe PR makes Discord message-history bootstrap, forward sync, and unlimited backfill return an error when a full page cannot advance its pagination cursor. Merge readiness⛔ Blocked until real behavior proof from a real setup is added - 7 items remain Keep this PR open: its cursor guards address a real infinite-pagination path, but unlimited backfill saves an invalid cursor before rejecting it, and the supplied proof exercises a mock client rather than the production Discord request boundary. Priority: P1 Review scores
Verification
How this fits togetherThe syncer fetches Discord channel-message pages and persists messages plus resume cursors in the local crawl store. The cursor selects each subsequent request during bootstrap, incremental sync, and full-history backfill. flowchart LR
A[Discord message page] --> B[Channel syncer]
B --> C[Persist messages]
C --> D[Validate next cursor]
D --> E[Next page request]
D --> F[Cursor error]
C --> G[Local sync state]
Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Validate the unlimited-backfill cursor before writing its checkpoint, preserve the last known-good cursor on failure, cover that durable-state invariant, and provide a redacted real-client request/response trace showing the cursor error. Do we have a high-confidence way to reproduce the issue? Yes, at the source level: the added client returns a repeated or empty full page and demonstrates the affected pager loop condition. The supplied evidence does not yet reproduce that response through the real Discord transport boundary. Is this the best way to solve the issue? No; the cursor checks are the right repair direction, but unlimited backfill must reject the cursor before persisting it and the fix still needs production-boundary evidence. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against 4c29bb75ef7f. LabelsLabel justifications:
EvidenceAcceptance criteria:
What I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (5 earlier review cycles)
|
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
Maintainer triage: LAND recommended using the credited, repaired implementation on The loop is reproducible. The submitted backfill guard also saved an empty checkpoint before rejecting the page, and its bounded path bypassed the guard entirely. The repair validates a full page before saving its backfill cursor, including one-page syncs. It retains the existing short-page and Built-CLI proof used real An independent source-blind validator reproduced the before defects and passed all seven repaired cases. Focused cursor/checkpoint tests and A broader syncer run exposed two pre-existing five-second timers expiring during SQLite fixture setup. Moving those operation deadlines after fixture setup preserves the actual timeout assertions; both previously failing tests now pass. Full-suite validation encountered CLI/share package timeouts under local load; lower-concurrency follow-up results will be included in the final handoff. Existing PR CI is green but does not cover this maintainer branch. |
Merge landed catalog cursor guards and apply the validated message pagination repair, including bounded backfill checkpoint validation and durable-state regression tests. Retain both documentation and changelog entries and move the two existing operation deadlines after fixture setup. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
|
Maintainer landing verification for The contributor branch now contains the validated checkpoint repair as a new commit, preserving contributor history and co-author credit. Both catalog and message regression sets, sync documentation, and changelog thanks remain. Codex autoreview returned no actionable findings. Both CLI binaries were rebuilt from this exact final head. Only the Discord base URL was changed at link time. The real CLI, production HTTP client, and disposable SQLite stores exercised synthetic loopback REST fixtures: All eleven scenarios passed. Archive catalog failures retain the existing best-effort warning policy. This is controlled HTTP integration proof, not a claim that live Discord returned malformed pages. |
A full message page with a repeated or missing cursor can leave bootstrap, forward sync, or backfill looping. The submitted backfill guard also saved an invalid checkpoint before rejecting the page and was bypassed by bounded passes. The repaired implementation validates each full backfill page before saving its resume cursor, including one-page syncs, so the last usable checkpoint survives an error.
This incorporates the credited repair from
triage/192-message-cursorsafter #181. Both catalog and message pagination regressions remain, with both sync documentation and Unreleased changelog entries. The original contributor commits and co-author credit are preserved. Two existing test operation deadlines now start after SQLite fixture setup, preserving their timeout assertions under load.Validation uses the built CLI, production Discord HTTP client, and disposable SQLite stores against synthetic loopback REST responses. Repeated bootstrap, forward, and backfill cursors stop after two message requests; missing cursors stop after one; the previous backfill checkpoint remains intact; bounded malformed pages are rejected; and a healthy three-message page succeeds. Both this smoke proof and #181's catalog smoke proof are rerun on the final head. This is controlled HTTP integration proof, not a claim of a live Discord incident. Final-head CI and proof results are recorded in the maintainer landing comment.