Skip to content

fix(peer): notice a dead link in 1.5s, not 3.2s — resume under the R1 gate - #84

Merged
frahlg merged 1 commit into
mainfrom
83-resume-detection
Aug 29, 2026
Merged

fix(peer): notice a dead link in 1.5s, not 3.2s — resume under the R1 gate#84
frahlg merged 1 commit into
mainfrom
83-resume-detection

Conversation

@frahlg

@frahlg frahlg commented Aug 29, 2026

Copy link
Copy Markdown
Member

netsim (#82) measured resume at 4.08 s direct and 4.50 s relayed, and showed
where it went: 3.23 s of it was detectioniceDisconnectedTimeout (2 s)
plus LinkGrace (1 s) — while the redial those constants gate was already
sub-second. So the beta's "under 3 s" could only come out of detection.

This takes it out. iceDisconnectedTimeout 2 s → 1 s, LinkGrace 1 s →
500 ms. iceKeepAlive stays at 500 ms, so detection is still two missed
keepalives rather than four: a single lost packet cannot tear down a live
session. iceFailedTimeout is unchanged.

Closes #83.

Measured

Nine flip reps per scenario, on the same harness and host as #82. Medians:

Scenario Path Resume before Resume after Detection before → after
flip-prc direct (STUN) 4077 ms 2564 ms 3.23 s → 1.75 s
flip-turn relayed (TURN) 4496 ms 2996 ms 3.23 s → 1.75 s

Spread after, over 9 reps each: flip-prc 2550–2685 ms, flip-turn
2962–3015 ms. Continuation 18/18. Full table in
netsim/results/results.md.

The redial is unchanged, as expected — 820–832 ms direct, 1227–1254 ms relayed.
The entire gain is detection.

Two honest caveats

Detection measures ~1.75 s, not the 1.5 s the arithmetic implies. pion checks
liveness on a keepalive-driven ticker, so the disconnected transition lands up
to one 500 ms interval late. The ~250 ms is that jitter, and it is stable across
all 18 reps (1702–1850 ms).

The relayed path meets the gate without margin. flip-turn resumes cluster
between 2.96 s and 3.02 s, so roughly half land just over 3 s. Its extra ~400 ms
over the direct path is the TURN allocation inside the redial. Holding the gate
on relayed sessions with room to spare means making that redial faster, which no
amount of detection tuning can do — worth its own issue rather than pushing
these constants further.

Separately, a ~1 s TURN retransmit occasionally lands on a dial or redial. It
predates this change — it is visible in the turn-only row that merged with
#82 (1262 / 2247 ms) — and looks like an ICE/TURN retransmission timer. When it
lands on a resume, that rep reads ~4 s. It showed up in 2 of 24 post-change
flip-turn samples and in the pre-change run alike.

Flap honesty

The concern with faster detection is that a marginal link trips teardown more
easily and gets misread as a flap. The classification itself is untouched —
ReconnectPolicy.MinHealthy (5 s) and the failure budget are unchanged — and the
measurements say it stayed honest:

  • Every one of 18 flips redialed on the first attempt, with no backoff sleep.
    That is directly visible in the numbers: a flap-classified drop sleeps
    Base = 1 s before retrying, so redial would read ≥1.8 s. It read 822–832 ms
    direct and 1227–1254 ms relayed — the healthy-drop path, which resets the
    budget and redials promptly.
  • No spurious teardown. No session dropped during the 7 s hold before its
    flip, across every rep of every scenario.
  • 18/18 continuations held, direct and relayed.

The real trade, stated plainly: a blip that heals between 1.5 s and 3 s used to
be absorbed and now costs a redial (~0.8 s direct). Since the redial is cheap and
the alternative is a frozen terminal, that is the right way round — but it is a
behaviour change, not a free win.

Also here

  • peer_link_test.go pins the sum. A new test asserts detection plus the
    measured redial fits the 3 s gate, that detection is at least two keepalives,
    and that failed still outlasts disconnected. Retuning any of it is fine;
    doing so without facing the gate is how it quietly reopens.
  • netsim records redials per rep (attempts) and lists any rep that needed
    more than one under a "Retried redials" heading. That is the signal to watch
    after a detection retune — a teardown the loop then could not immediately
    recover from. This run had none.
  • netsim/run.sh honours an exported NETSIM_REPS, which it previously
    clobbered with the per-scenario default. NETSIM_REPS=9 ./run.sh flip-turn now
    samples a tail properly, which is how the numbers above were taken.

Checks

cd go && go test ./... green, -race green on peer/client/agent, gofmt -l .
empty, go vet ./... clean, cd web && npm test 152/152 (after npm ci),
./scripts/verify-reproducible.sh byte-identical. No web constant changed —
disconnect-grace.js cites browser-side timings, not these.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KeiotDVE94wEzvc7wcvm1y


Note

Medium Risk
Changes production ICE teardown timing on all attaches, which can increase redials on marginal links but is bounded by existing reconnect policy and netsim flap checks.

Overview
Cuts ICE link-death detection so post-flip resume can meet the R1 “under 3s” gate: iceDisconnectedTimeout goes from 2s to 1s and LinkGrace from 1s to 500ms (still two missed 500ms keepalives before disconnected). Netsim showed ~3.2s of a ~4s resume was detection while redial was already sub-second.

Direct flip resume median drops to ~2.56s; relayed flip-turn clusters around ~3.0s with little margin. Tradeoff: brief outages that heal between ~1.5s and ~3s now trigger a cheap redial instead of being absorbed.

Harness and guardrails: peer_link_test asserts detection budget + measured TURN redial stays under 3s; netsim records per-rep reconnect attempts and highlights multi-attempt redials; run.sh respects an exported NETSIM_REPS for tail sampling. Updated README and committed results.md from 9-rep flip runs.

Reviewed by Cursor Bugbot for commit c73dddc. Bugbot is set up for automated code reviews on this repo. Configure here.

… gate

netsim (#82) measured resume at 4.08s direct and 4.50s relayed, of which 3.23s
was detection: iceDisconnectedTimeout (2s) plus LinkGrace (1s). The redial it
gates was already sub-second, so the beta's "under 3s" could only come out of
detection.

iceDisconnectedTimeout 2s -> 1s (two missed 500ms keepalives instead of four)
and LinkGrace 1s -> 500ms. Keepalive is unchanged, so a single lost packet still
cannot tear down a live session.

Measured over 9 flip reps each, medians:

  flip-prc    resume 4077ms -> 2564ms   (detection 3.23s -> 1.75s)
  flip-turn   resume 4496ms -> 2996ms

Detection reads ~250ms above the 1.5s arithmetic because pion checks liveness on
a keepalive-driven ticker, so the transition lands up to one interval late.

Flap accounting is untouched and stayed honest: every one of 18 flips redialed
on the first attempt with no backoff sleep (redial 822-832ms direct, i.e. the
healthy-drop path), 18/18 continuations held, and no session was torn down
before its flip.

Also here:
- peer_link_test.go pins the detection-plus-redial sum against the 3s gate, so a
  future retune has to face it deliberately.
- netsim records redials per rep and reports any that needed more than one; that
  is the signal to watch after a detection retune.
- netsim/run.sh honours an exported NETSIM_REPS, which it previously clobbered.

Closes #83

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeiotDVE94wEzvc7wcvm1y
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 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-08-29T12:47:20.375932Z c73dddc 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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c73dddc7f1

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const (
resumeGate = 3 * time.Second
measuredRedial = 1250 * time.Millisecond // netsim flip-turn, the slower path
detectionBudget = iceDisconnectedTimeout + LinkGrace

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include keepalive jitter in the resume budget

When the ICE liveness check runs near the end of its keepalive tick, the disconnected transition can arrive up to iceKeepAlive later than iceDisconnectedTimeout; the commit's own netsim notes describe this jitter and report flip-turn samples above the 3 s gate. By budgeting only iceDisconnectedTimeout + LinkGrace, this test asserts 2.75 s while the configured upper budget is 3.25 s after adding the 1.25 s TURN redial, so it passes despite not actually pinning the stated p90 requirement. Include the keepalive scheduling delay in the budget or validate the empirical p90 instead.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved. Cursor Bugbot completed successfully with no findings that need human review; no reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@frahlg
frahlg merged commit 0d604d1 into main Aug 29, 2026
5 checks passed
frahlg added a commit that referenced this pull request Aug 29, 2026
Netsim (#82, #84) measured the matrix; the gap that remains is real-network
data, so say that instead.


Claude-Session: https://claude.ai/code/session_01KeiotDVE94wEzvc7wcvm1y

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

R1 follow-up: resume under 3 s for real — detection, not redial

1 participant