Skip to content

fix(net): report a JS IETF FETCH group evicted after listing as unknown - #7150

Merged
kixelated merged 4 commits into
mainfrom
quest/m1/js-fetch-evicted-unknown
Oct 29, 2026
Merged

kixelated merged 4 commits into
mainfrom
quest/m1/js-fetch-evicted-unknown

Conversation

@kixelated

@kixelated kixelated commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m1/js-fetch-evicted-unknown.md, and deletes it along with its link from the m1 README.

Summary

Sometimes the cache evicts a group after a JS IETF FETCH answer or a draft-22 fill has listed it but before it gets written. The publisher used to skip that group without saying anything, and a skip on a fetch stream means the group does not exist. It now sends End of Unknown Range (0x10C) covering the group's whole slice, on both drafts 18 and 22.

  • js/net/src/ietf/publisher.ts: FetchWriter gets an unknown() marker next to timedOut(). Both now go through one #gap(reason, ...) helper, so the evicted group gets the same treatment a timed-out one already did. If nothing went out since the prior marker, the groups skipped before it are first marked nonexistent (0x8C), because a marker covers every Location since the prior one. #answerFetch (the "Gone since it was listed" path) and #runFill (the !group path) call it in place of continue. Nothing ends the FETCH early, and FETCH_OK's end is unchanged.
  • I reworded the comment on the resolution loop before FETCH_OK. It said the response "skips" a missing group. A group missing from the top of the range still moves FETCH_OK's end below it, as before.
  • Tests run on a manual clock and use real cache aging (the 30 s window), with no hooks mocked. A wait on an open group gives the older listed groups time to age out:
    • fetch.test.ts "a group evicted after it was listed is unknown": drafts 18 and 22, both orders. It includes a never-existing group 0, to check that it still reads as nonexistent ahead of the Unknown marker.
    • publisher.test.ts "draft-22: a fill marks a group evicted after it was listed unknown": only draft 22, because only draft 22 has fills.
    • I ran both tests against the old publisher and both fail there with the markers missing.

Impact

  • Public API: none.
  • Wire: a FETCH or fill group evicted between listing and writing now goes out as End of Unknown Range (0x10C) instead of being left out. The marker and framing already exist in both drafts, so no IETF draft text changes.

Rust IETF publisher has the same skip (not changed here)

Per triage, I did not touch the Rust IETF publisher because moq-dev/moq#6999, moq-dev/moq#7038 and moq-dev/moq#7085 are working in it. It skips in both matching places:

  • rs/moq-net/src/ietf/publisher.rs, the FETCH answer loop in serve_fetch_stream: Err(Error::NotFound | Error::NotFetchable | Error::Unsupported | Error::Old) => continue, with the same "Gone since it was listed ... absent from the answer" comment.
  • rs/moq-net/src/ietf/publisher.rs, run_fill: a fetch_group failure with those errors on a range fill also hits continue.

Rust re-reads through fetch_group and can refetch upstream, so for Rust a skip comes from a failed refetch rather than only from eviction. The same fix still fits there: NotFound/Old on a listed group becomes 0x10C. Unsupported/NotFetchable may deserve their own reading. This looks like a follow-up quest once those PRs land.

Choices made without asking

  • The evicted group's marker covers its whole slice and reuses the timed-out path's end rule: the slice's last object, or the maximum Object ID for a whole group. The FETCH_OK end does not change.
  • I did not run just test interop --all. Nothing about the framing changes, and interop does not exercise eviction.

Checks

  • bun test in js/net: 2587 pass.
  • bun run check (tsc) and biome on the changed files: clean.
  • just check: passes.
  • quest check: ok.

Suggested follow-ups

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 2 commits October 28, 2026 15:04
A group the cache evicts between listing it for a JS IETF FETCH answer or
fill and writing it now goes out as End of Unknown Range (0x10C) on drafts
18 and 22, instead of a silent skip that reads as the group not existing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title JS IETF FETCH reports an evicted group as unknown fix(net): report a JS IETF FETCH group evicted after listing as unknown Oct 28, 2026
@kixelated
kixelated marked this pull request as ready for review October 28, 2026 22:24
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 17 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 453a2761-d082-4dce-a1f9-0fb0d8f3c8bb
Commits

Reviewing files that changed from the base of the PR and between b028c59 and 0118341.

Files selected for processing: 6
  • js/net/src/ietf/fetch.test.ts
  • js/net/src/ietf/publisher.test.ts
  • js/net/src/ietf/publisher.ts
  • quest/m1/README.md
  • quest/m1/ietf-publisher-one-group.md
  • quest/m1/js-fetch-evicted-unknown.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T05:09:58.618146Z 0118341 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: ae4cbc7.

No actionable bugs found in the changed paths. Reporting a listed-but-evicted group as Unknown corrects the wire meaning without changing FETCH_OK's boundary. Reusing the existing gap writer is simpler than separate marker logic and preserves the NonExistent prefix before an unknown slice. The tests cover both FETCH drafts/orders and draft-22 fill using actual cache aging. The Rust parity issue documented in the PR remains outside this JS change.

Verification: static review of the diff, FETCH resolution/answer and fill loops, slice calculations, and marker writer. I did not run tests or interop.

kixelated and others added 2 commits October 28, 2026 21:36
…cted-unknown

Keep this PR's deletion of quest/m1/js-fetch-evicted-unknown.md over main's
Plan rewording, and point the one-group quest's link to it at the landed
FetchWriter.unknown() instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary:

  • Merged main twice to clear conflicts. The first was a link-list conflict in quest/m1/README.md, which the quest merge driver resolved. The second came from moq-dev/moq#7194, which reworded this quest's Plan. I kept the deletion, because this PR finishes the quest.
  • quest/m1/ietf-publisher-one-group.md (added on main) linked the deleted quest. That line now points at FetchWriter.unknown() from this PR. The quest's plan is unchanged.
  • js/net: bun run check and bun test (2591 pass) on the merged tree. CI is green on 0118341237f88b2448c8383811dbf0dfb7e6dabf, Codex has no findings on that head, and quest check --base origin/main passes.
  • The Rust counterpart is already planned as quest/m1/ietf-publisher-unknown-range.md in moq-dev/moq#7195.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 7c47075 Oct 29, 2026
11 checks passed
@kixelated
kixelated deleted the quest/m1/js-fetch-evicted-unknown branch October 29, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant