Skip to content

Backwards DTS at a failover switch: the always-present-step explanation is refuted, and the mechanism is unknown #126

Description

@rainmanjam

Important

Update 2026-08-13 — retitled. The rate framing is retired, and the leading
explanation is refuted.

One run on main at c3a1bc1 emitted no NEARMISS at all across nine
seams: not one backward step of any magnitude, sub-millisecond included. The
"a small step is present at every seam and a timing change merely widened it"
explanation does not hold.

The old title said 3 runs out of 10, and only on the core-review branch.
Both halves are now misleading: that branch is long merged and deleted, and
the rate was never the useful quantity — with no mechanism, more runs make a
number more precise without making it more meaningful. Deliberately NOT
pursued for that reason.

The one lead is seam 6, which hit its stop deadline with a 12-second
teardown, meaning the outgoing feed was not confirmed stopped before the
incoming one began. Measured on a passing run. See the comment below.

Important

Update 2026-08-11 — the rate below is stale, and stale in the direction
that gets this deprioritised.

This issue was filed on a single unreproduced CI failure, and the "What is
not known" section proposed running the suite ~20 times a side to settle it.
That experiment was run. Commit 79b16f8 (PR #152) reports:

a backwards decode timestamp at a failover switch: 3 runs of 12 under one
timing change, 0 of 12 under another
, and the mechanism is still not
established.

So it reproduces at roughly 1 in 4 under one timing condition and not at
all under another. It is not a one-off. Read the update at the bottom before
judging severity from the original text.

What happened

acceptance-failover failed once on PR #125 with a single assertion:

FAIL  1 backwards DTS step(s) — a platform drops the connection on these
      25 passed, 1 failed

Re-running the identical commit passed. It has not reproduced since.

Observation Result
CI, PR #124 (parent) pass
CI, PR #125 attempt 1 FAIL — 1 backwards DTS step
CI, PR #125 attempt 2, same SHA pass
Local run 1 pass, 26/26
Local run 2 pass
Local run 3 pass

Why this is not #94

#94 documents the known
acceptance flake as a binary stall: a suite consuming its whole 20-minute
budget, with measured medians of 185s and no duration tail. This failure ran to
completion in 4m26s, reached step 9, and failed one assertion. Different
signature. It should not be filed under #94 and it should not be assumed benign
because #94 exists.

Why it matters more than a flake normally would

The check is zero-tolerance by design, and the reason is in the script:

A feed started without -output_ts_offset republishes from zero, so a switch
hands the destination a timestamp behind the one before it, and a platform
answers a backwards jump by dropping the connection.

So a single backwards DTS step is not a test artifact — it is the failover tier
occasionally doing the exact thing failover exists to prevent, on a real switch,
in a real recording. The suite caught a genuine intermittent. Whether it happens
once in four runs or once in forty, a dropped platform connection mid-broadcast
is the outcome.

What is not known

Whether the rate changed. PR #125 refactors the selector (extracted to
selector.go), changes primaryFeedSig to include the upstream hub's port, and
coalesces status pushes on a 150 ms leading-edge window. Any of those could
perturb switch timing relative to a GOP boundary. Establishing whether the rate
moved needs N runs on main against N on the branch — roughly 5 minutes each,
so ~20 runs a side to say anything with confidence. That has not been done.

The honest position is: one occurrence, not reproduced, cause unknown, and the
possibility that it is a pre-existing intermittent has not been separated from
the possibility that this branch made it likelier.

Superseded 2026-08-11 — see the banner at the top and the update below.
The 12-runs-a-side experiment this section asked for was carried out.

Suggested next step

Run the suite ~20 times on main and ~20 times on a branch with these changes,
counting backwards-DTS occurrences on each side. If main shows the same rate it
is pre-existing and wants its own investigation into the switch seam. If only the
branch shows it, the status coalescing is the first thing to look at.


Update 2026-08-11 — measured, still unfixed

Recorded here because the numbers lived only in a commit body, and this issue
is what anyone triaging reads.

The rate

From 79b16f8 (PR #152): 3 runs of 12 under one timing change, 0 of 12 under
another.
The mechanism is still not established. What the original text called
"one occurrence, not reproduced" is now a measured intermittent under a known
condition.

Two proposed fixes, both refuted, both for the same reason

BOTH REFUTED FIXES FOR #126 RESTED ON THE SAME UNMEASURED ASSUMPTION.

The argument in ensureFeed is about whether the incoming feed's offset is
taken before or after the teardown — and that only means anything once everyone
agrees what -output_ts_offset does with the number. Nobody had measured it.
There is no -copyts in the tree, so the input's own start time is a live
variable, and MPEG-TS does not start at zero. An offline bench against the
production relayFeedArgs was added rather than against a copy of it.

Why the old evidence could not settle anything

The suite printed one number for the whole file, which cannot distinguish
"one sub-millisecond step somewhere" from "a sub-millisecond step at EVERY
seam". Those are the leading hypothesis and its refutation: if a small backward
step is present at every switch all the time, a timing change that widens it
merely pushed an existing step over the threshold, and the offset was never the
cause.

What landed instead of a fix

A seam ledger — one Info line per handover, written where the handover
happens, recording which feeds swapped, where on the tier clock, how long the
teardown took, what the ledger predicted, and how many backward steps of any
magnitude landed in that seam's interval. Step 9 of the acceptance suite now
attributes each backward DTS step to the switch that produced it.

79b16f8 is explicit: "No fix is claimed and #126 stays open. This only makes
the next occurrence"
attributable.

Next step

The next reproduction should now name its seam. Until one is captured with the
ledger active, the mechanism stays open — but this should be triaged as a
reproducible intermittent in failover, not as a single unexplained CI blip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:productUser-visible behaviour and features

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions