Skip to content

feat(router): instant warm-standby failover so a leg death never dead-ends a connection - #4207

Merged
0pcom merged 1 commit into
skycoin:developfrom
0pcom:feat/instant-standby-failover
Aug 26, 2026
Merged

feat(router): instant warm-standby failover so a leg death never dead-ends a connection#4207
0pcom merged 1 commit into
skycoin:developfrom
0pcom:feat/instant-standby-failover

Conversation

@0pcom

@0pcom 0pcom commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

The warm-standby reserve (now 512 deep) only switched in on the periodic rotation tick — up to a full interval (~20s) after an active leg died. For a lean active set that's a real dead-connection window, defeating a 'switch in at a moment's notice' reserve.

Two changes, both leaving the rotation interval itself untouched (its cadence still governs UDP/sudph keep-alive + anti-churn):

  • Selector emergency fallback (route_mux.go): when selectTransport finds no active leg selectable (all dead/not-ready), it falls through to any alive, ready warm-standby leg instead of failing the send. A parked leg keeps its rules + transport alive, so it carries the packet immediately — the connection survives as long as any leg is alive, zero promote latency.
  • Event-driven promote (route_group.go): a leg death signals the rotation loop (rotateNow, buffered-1, non-blocking) to run its controller at once, so drop-recovery promotes a standby immediately. servicePacketLoop gained an optional trigger channel (nil for other loops).

Full router suite green; new test covers legSelectableIgnoringStandby.

…-ends a connection

The warm-standby reserve (now 512 deep) only got switched in on the periodic
rotation tick — up to a full rotation interval (~20s) after an active leg died.
For a lean active set that meant a real dead-connection window, defeating the
point of a 'switch in at a moment's notice' reserve.

Two changes make failover instant, both leaving the rotation interval itself
untouched (its cadence still governs UDP/sudph keep-alive and anti-churn):

- Selector emergency fallback (route_mux.go): when selectTransport finds NO
  active leg selectable (all dead/not-ready), it now falls through to any alive,
  ready warm-standby leg instead of returning ErrNoSuitableTransport. A parked
  leg keeps its rules installed and its transport alive, so it carries the packet
  immediately — the connection survives as long as ANY of the group's legs is
  alive, with zero promote latency. legSelectableIgnoringStandby is legReadyAt
  without the standby exclusion, so an unconfirmed leg is still never used.

- Event-driven promote (route_group.go): a leg death now signals the rotation
  loop (rotateNow, buffered-1, non-blocking) to run its on_tick controller AT
  ONCE, so drop-recovery promotes a warm standby into the active set immediately
  rather than on the next interval. servicePacketLoop gained an optional trigger
  channel (nil for the non-rotation loops, so they are unchanged).

Together: the selector keeps traffic flowing the instant the active set is lost,
and the immediate tick restores a proper active set right after. Full router
suite green; new test covers legSelectableIgnoringStandby.
@0pcom
0pcom merged commit 23412d9 into skycoin:develop Aug 26, 2026
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