Skip to content

fix(moq-mux): a failed stitch returns to a live export; a return during the grace is followed - #5249

Merged
kixelated merged 1 commit into
mainfrom
fix/ts-follower-stitch-grace
Oct 10, 2026
Merged

kixelated merged 1 commit into
mainfrom
fix/ts-follower-stitch-grace

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

#5147 merged with two ts::Follower state-machine findings still open on its final head:

  • CodeRabbit, corroborated by the OpenAI review: a return still waiting for its catalog's first snapshot runs as Running { settling: Some }. If a stitch then starts and its replacement goes before it resolves, the Follower restores Settling, which never polls the still-live export. Its later frames are lost, and it ends at the old linger deadline.
  • OpenAI: after an export failure starts the error grace, an End and a same-epoch Start can both arrive before the next poll. serving reads Ours again, so the grace is kept and the follower fails with the old error instead of following the return.

Approach

  • State::Following records live, whether it came from Running (a stitch mid-stream). A failed resolution goes back to Running with its settling intact, and only a follow from Settling goes back to Settling.
  • The grace clears when an end was observed (ended), not only when something else serves the path.

Each fix has a regression test that fails without it:

  • a_follower_keeps_a_return_awaiting_its_catalog_when_a_stitch_goes ends 10 s after start without the fix, instead of 13 s.
  • a_follower_follows_a_return_that_came_back_during_the_grace fails at the grace without the fix.

Impact

  • No public API or wire change. Behavior only, within moq_mux::container::ts::Follower.

Alternatives

  • Holding the prior State boxed inside Following. A bool is smaller and keeps the transitions explicit.

Follow-ups

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

…he grace is followed

A stitch that fails to resolve while a return still awaits its catalog now goes back to
running that export, rather than settling and leaving it unpolled. A failure whose
broadcast went and came back before the follower looked clears the grace and follows the
return instead of failing as the export's own.

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

coderabbitai Bot commented Oct 10, 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 14 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
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ccbcbeb0-17a9-42d5-bf5d-89444945b144

📥 Commits

Reviewing files that changed from the base of the PR and between 24b6473 and 01326c1.


📒 Files selected for processing (2)
  • rs/moq-mux/src/container/ts/export_test.rs
  • rs/moq-mux/src/container/ts/follower.rs

  • 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 10, 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-10T19:55:02.592038Z 01326c1 PR opened
ℹ️ 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

Copy link
Copy Markdown
Collaborator Author

Grok review of 01326c10

Both fixes look correct and are tightly scoped. The live flag makes the failed-resolution path go back to Running { settling } for a mid-stream stitch, so a return awaiting its catalog keeps being polled. Clearing the grace on self.ended (follower.rs:222) lets the Settling → Following transition at line 238 pick up a same-epoch return instead of failing with the old error. Each fix comes with a regression test.

Blocking: none.

Non-blocking

  1. follower.rs:303: when live is true and settling is Some, the old deadline can still fire while Following. That ends a return that's live but hasn't snapshotted yet, at the original linger deadline. It's the same rule Running { settling: Some } applies at line 192, so it's consistent, but the new test only covers the path where resolution fails. A test where the deadline passes while the replacement is still resolving would pin this down.
  2. With the new grace condition, a real export failure followed by an end and a return within one poll is treated as a failure that isn't the export's own. If the return keeps failing the same way, each cycle restarts without a grace error. That's probably fine, but it's worth a sentence in the doc comment.
  3. CI is still running (Check, Test, Android, Windows, macOS).

Verdict: MERGE

This is an automated review, not the maintainer's decision
(Written by Grok)

@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: 01326c1

Both outstanding Follower findings from #5147 are addressed:

The explicit live flag is a proportionate fix without boxing the prior state. Both paths have focused regressions. No additional confirmed bug or necessary simplification found.

Verification: GitHub-only static inspection of the full PR diff, relevant implementation/tests, and review history. No tests executed; CI results were not independently verified.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Replying to the Grok review's non-blocking items:

  1. That is the intended rule: Following { live: true, settling: Some } keeps the deadline Running { settling: Some } would, so a return that never snapshots still ends at its linger. This PR only changes where a failed resolution goes back to, so I'm leaving the extra deadline test out of scope.
  2. The inline comment at follower.rs:221 already states the rule (a broadcast that went, even one already back, was no failure of the export's own). A return that fails on its own still gets the grace, since it is the one serving when it fails. No extra doc sentence.

(Written by Claude Opus 5.5)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for 01326c10:

  • Changes: ts::Follower records whether a stitch started mid-stream (live), so a failed resolution returns to Running { settling } and keeps polling a return awaiting its catalog. The error grace clears once an end is observed, so a same-epoch return during the grace is followed. Each fix has a regression test.
  • Reviews: OpenAI review and a Codex thumbs-up on this head, no findings. Grok's two non-blocking items were replied to above, no code change.
  • CI: all checks pass.
  • Decisions: none outstanding. No public API or wire change.

Enqueuing with auto-merge.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit 34c1007 Oct 10, 2026
6 checks passed
@kixelated
kixelated deleted the fix/ts-follower-stitch-grace branch October 10, 2026 20:25
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.

1 participant