Expand description
A multi-station connection pool: dials several Sessions concurrently
(bootstrap seeds, optionally grown by discovering more via
hecate_stations.list_stations) and gives Pool::call/
Pool::publish a choice of which connected one to use, instead of a
caller managing a single Session by hand.
Call/Publish only — no pooled Subscribe. Session::run_subscriber’s
own doc (and Session::call’s) already say a control stream can’t
safely serve an in-flight Call’s response-wait and an ongoing Subscribe
EVENT loop at once — each discards frames it doesn’t recognize, so they’d
steal each other’s frames. Building a pool-wide Subscribe fan-out
properly would need either a second Session per link dedicated to it,
or a real frame-demultiplexing layer on top of Session (dispatch by
call_id/frame-type to whichever waiter wants it) — genuinely new
infrastructure, out of scope here. A caller that needs Subscribe still
uses a bare Session::subscribe/Session::run_subscriber directly,
unpooled, exactly as before this module existed.
Ported from the same station-discovery/link-rotation design already
shipped in macula-go (pool/discovery.go, v0.7.0) and macula-dotnet
(StationDiscovery.cs, v0.4.0) — see those crates’ own doc comments for
the fuller cross-language history. This is a from-scratch build, not a
port of an existing pool: this crate had no Seed/multi-link concept at
all before this module.
Per-link trust, not one fixed mode for the whole pool — this is the
one deliberate design difference from the go/dotnet ports, made possible
by building from scratch rather than extending an existing single-Trust
pool: a discovered station whose directory row has NO hostname (only a
bare-IP host_advertised) but DOES carry a node_id dials under
Trust::Pinned(node_id) instead of being skipped outright the way
go/dotnet’s ports skip every hostname-less row under Trust::WebPki
(which can never validate a bare IP with no IP SANs). The underlying
MECHANISM mirrors a shipped, live-verified precedent in a completely
different codebase: macula-apps/macula-cam2me’s Android client
(reachability/StationDiscovery.kt), confirmed against the real fleet
by 34 (macula’s own reference-implementation session) independently
reaching the identical conclusion this module reaches, including a
live TLS-layer verify=none warning from macula_quic when dialing a
hostname’d station by IP+Pinned instead of its usual WebPki path.
This module’s PRIORITY ORDER deliberately differs from cam2me’s own,
in the safer direction — cam2me picks Pinned(node_id) whenever a row
carries a node_id at all (true of essentially every row), falling back
to hostname/WebPki only when host_advertised itself is missing; that
trades away TLS-layer MITM resistance for the common case, not just the
no-DNS one. Here, [dial_target_from_station_row] prefers hostname
unconditionally — Trust::Pinned is chosen only when a row has NO
usable hostname at all, so a normal Let’s-Encrypt-backed station still
dials WebPki exactly as it always has; only a genuine no-DNS station
(stations-linode-toronto — see tests/live_station.rs’s own
pinned_trust_full_handshake_succeeds_against_toronto) ever falls to
Pinned. Bootstrap seeds are entirely unaffected either way — they
always dial under the pool’s own configured Trust.
Structs§
- Link
Info - Snapshot of one link, for health/introspection.
- Pool
- A multi-station connection pool — see this module’s own doc for the full design.
- Pool
Options - Tunables for
Pool. Defaults match every other port of this feature. - Pool
Status - Aggregate health snapshot. Lock-free best-effort read.
- Pooled
Link - One configured link’s current state. Never removed from
Pool’s ownlinkslist once added (see that field’s own doc) —connectedsimply goes false when the link is down or still dialing. - Seed
- A dial target: host+port only, no identity attached (every link in a
pool shares the pool’s one identity). Mirrors macula-go’s
connection.Seed/ macula-dotnet’sSeedrecord — this crate had no equivalent type before this pool. - Station
Discovery Options - Configures opt-in discovery of additional stations via
hecate_stations.list_stations, layered on top of the caller-supplied bootstrapSeeds. Default (enabled == false) is a complete no-op.
Enums§
- Link
Selection - How
Pool::call/Pool::publishorder the pool’s currently-connected links before applying their own existing first-match/replication_factorlogic — changes ORDER only, never how many links get used. Matches macula_client.erl’s ownlink_selectionoption (first_success/random) and macula-go/macula-dotnet’s identically-named enum, so config ported from any of those doesn’t need re-learning. - Pool
Call Error - Pool
Publish Error