Skip to content

fix(mux): measure live import idle gaps on the async clock - #4721

Merged
kixelated merged 5 commits into
quest/m1/test-flakes-2/READMEfrom
quest/m1/test-flakes-2/mux-live-import-clock
Oct 3, 2026
Merged

kixelated merged 5 commits into
quest/m1/test-flakes-2/READMEfrom
quest/m1/test-flakes-2/mux-live-import-clock

Conversation

@kixelated

@kixelated kixelated commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

TS, fMP4, and FLV live-import restart tests blocked their threads for a 300 ms idle gap because the broadcast clock read real time.

Approach

Store the private monotonic epoch as web_async::time::Instant, convert native std::time::Instant inputs at the boundary, and advance paused Tokio time in the import fixtures. A clock regression covers fixed wall mapping, timed and untimed writes, and invalid captures. All four paused regressions fail with the original clock.

Impact

  • Public API: existing std::time::Instant signatures stay unchanged; browser inputs of this native type return an explicit unsupported error.
  • Wire: unchanged; the wall mapping remains fixed.

Alternatives

Rejected injecting arrival timestamps into importers only for tests, and changing public instant types.

Follow-ups

Clock::new() still samples std::time::SystemTime; its pre-existing browser limitation remains outside this native test-clock quest.

Validation

  • Original three restart tests: 340 to 370 ms each, with real sleeps.
  • Paused regression reproduction: all four fail before the fix and pass after it.
  • nix develop --command just check passed: 2,349 default tests, 387 capture tests, 132 play tests, and 78 minimal-video tests; media feature contracts, JS/doc checks, and repository lints passed.
  • nix develop --command just fix and just rs wasm passed. Existing CI runs the new regressions through scoped Rust checks.
  • The TS restart shift allows two 90 kHz ticks: with an exact idle gap, each pass's offset truncates to a source tick, which failed about two of three runs by 1 us. 40 of 40 runs pass after the change.

(Written by GPT-6, updated by Claude Opus 5.5)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Completed the quest. The private async epoch lets all three live-import restart fixtures advance paused time, and all four paused regressions fail against the original implementation. Public native Instant signatures and the wire stay unchanged; browser native Instant inputs fail explicitly.

Local just check, just fix, just rs wasm, and quest check passed. Leaving this PR as a draft for the parent task's review and landing workflow. Suggested follow-up: address Clock::new()'s existing browser std::time::SystemTime sampling limitation.

(Written by GPT-6)

@kixelated
kixelated marked this pull request as ready for review October 2, 2026 15:22
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome under /recommended: the private monotonic epoch now uses web_async::time::Instant, preserving native std::Instant input signatures. All four mock-time regressions were red before the fix and green afterward, and required checks and wasm compilation passed. Browser std::Instant inputs now refuse explicitly through the existing error type; Clock::new retains its pre-existing browser wall-sampling limitation, so this is not full browser clock support. Wire unchanged. Ready for review and the merge course; report the wall-sampling limitation as a separate follow-up.

(Written by GPT-6)

@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: e4d26c6

No actionable bugs found. The direction is sound: rs/moq-mux/src/clock.rs:26–37, 86–133 moves elapsed-time measurement onto the async clock while preserving native std::time::Instant inputs and the fixed wall mapping. The new clock regression checks elapsed time, wall conversion, timed/untimed writes, and invalid captures. All multi-chunk TS/fMP4/FLV fixture calls that reach time::advance now run under paused time; the unpaused callers pass a single chunk.

The existing browser SystemTime::now() limitation is explicitly disclosed and remains outside this change; this does not establish full browser clock support.

Verification: static review of the diff, clock/dependency behavior, fixture callers, and test wiring. I did not run Rust tests, wasm compilation, or quest check; the author’s reported before/after and local-suite results were not independently reproduced. GitHub’s main checks were still running when inspected.

(Written by OpenAI Codex)

@kixelated

Copy link
Copy Markdown
Collaborator Author

The exact-head Codex review and CI pass. The SHA-pinned auto-merge request was refused by GitHub: Protected branch rules not configured for this branch. Leaving this ready without changing branch protection or using another merge path.

(Written by GPT-6)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Switches the private broadcast-clock epoch to web_async::time::Instant so TS/fMP4/FLV live-import restart fixtures can tokio::time::advance a paused clock instead of std::thread::sleep, while keeping public std::time::Instant inputs and converting at the boundary.

Findings

No concrete issues found.

The production path (Anchor::translate → Clock::now) and the three restart fixtures correctly share the async monotonic clock; single-chunk non-paused callers never hit tokio::time::advance. The new paused_clock_preserves_native_boundaries regression covers timed/untimed stamp, wall stability under advance, and InvalidCapture for ahead-of-now / before-epoch. Browser refusal of native Instant inputs via monotonic is intentional and documented; Clock::new() still samples async time directly so it keeps working on wasm.

Process note (non-blocking for the change itself): head is behind base and GitHub reports mergeable: CONFLICTING — almost certainly the quest README checklist (this PR drops the mux-live-import-clock row; base dropped the tracing-capture-audit row after #4713). Rebase onto quest/m1/test-flakes-2/README before merge.

CI

Check / Test / Quest / Android / macOS / Windows all green on e4d26c65.

Verdict: MERGE on head e4d26c65cc859bda3449f743e598c1273039e3d4

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

kixelated and others added 3 commits October 2, 2026 21:14
…nto mux-live-import-clock

# Conflicts:
#	quest/m1/test-flakes-2/README.md
…nto mux-live-import-clock

# Conflicts:
#	quest/m1/test-flakes-2/README.md
The paused clock makes the idle gap exact, exposing the translator's
truncation of each pass's offset to a 90 kHz tick, which failed about
two of three runs by 1us.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated merged commit 25709da into quest/m1/test-flakes-2/README Oct 3, 2026
6 checks passed
@kixelated
kixelated deleted the quest/m1/test-flakes-2/mux-live-import-clock branch October 3, 2026 05:23
@kixelated

Copy link
Copy Markdown
Collaborator Author

Merged into quest/m1/test-flakes-2/README at 179baad.

  • Merged the questline base twice, after test(tokio): run fixed-address WebSocket TLS dials on real time #4722 and then test(publish): mock the audio delay clock #4715 landed. The only conflict was the Required list; each side had removed its own finished quest.
  • Fixed a flake this PR introduced: with the idle gap now exact, ts::import_test::live_import_restarts_forward_after_idle failed about 2 of 3 runs by 1 us. Anchor::translate_at converts the micros offset to the 90 kHz source timescale by truncating, so each pass loses a different fraction of a tick. The assertion now allows two ticks. FLV and fMP4 are unaffected because their source micros are whole numbers. It passed 40 of 40 runs locally, and CI is green.
  • Follow-up: a restart can land up to one source tick short of the idle gap. In practice this doesn't matter, but if exactness is wanted, reanchor could round the offset up to a source tick.

(Written by Claude Opus 5.5)

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