A router reported its links to every controller, and each controller kept its own
picture built only from what routers told it directly. That does not survive
routers being connected to a subset of controllers: a controller learns nothing
about links whose routers it does not hold a connection to.
Link state now lives in the replicated store: a router reports to one controller,
that controller writes the entry it owns, and the mesh carries it to the rest.
Each link entry is owned by the router that dialled it, so two controllers never
contend for the same key, and a controller that has never spoken to a router
still converges on its links.
- registers a link state type on the gossip store and carries link add, update
and removal through it
- makes a link's source router an atomic and repoints it when the router
connects, since a link can be built from a gossiped entry before its router has
connected here, leaving a database-loaded placeholder as the endpoint
- reconciles a reconnecting router's gossip entries, marking its links usable
again rather than removing them, since a disconnect sets them down instead of
deleting them
- tombstones a link on disconnect in single-controller mode, where there is no
peer to learn the removal from
- adds the gossip transport: peer handlers on the controller mesh, router-facing
gossip handlers, digest exchange off the receive goroutine, and the pools that
bound apply and I/O work
- has the digest exchange restamp a key the controller holds a higher version
for, above that version, and send the live value. A router's Lamport clock is
in memory, so a restart returns it to zero while the controller still holds
versions from the previous incarnation under the same key. Link metrics are
keyed by link id alone, and that id belongs to the dialer, so an acceptor's
restart leaves the key unchanged and its republishes are refused as older.
Keeping the stored version sends nothing, and every later digest reaches the
same answer, so the exchange that exists to repair divergence would instead
hold it in place. Safe because the router is the sole writer of the keys it
advertises: it takes the clock from a digest but never a value
- advertises a gossip capability so a router reports to one controller only once
every controller can replicate, and falls back to reporting to all until then
- adds canaries, a per-router sequence carried over the same path, so a router
can tell that a controller has stopped applying its state
- carries link metrics over gossip alongside the state
- keeps the disconnect teardown's reroute ordering: the currency guard wraps it,
and inside, the link snapshot and MarkDisconnected stay ahead of the cascade so
reroute cannot path through the router being removed
- adds a link ConfigHandler (router/link FactoryRegistry) that applies router.link.v1 config: Apply rebuilds the listener/dialer set wholesale, and established Xlinks survive because Listener.Close() only closes the accept loop
- translates local link: YAML into router.link.v1 JSON and pushes it through the managed-config registry at startup
- adds the UpdateLinkListeners ctrl message so the router republishes its listener set to the controller on change; the controller re-fans via the existing PeerStateChange path
- re-evaluates dialers on link group and listener changes via RescanForDialOpportunities
For #3743.
- channel.TypedReceiveHandler -> channel.ContentTypeReceiver
- binding.AddTypedReceiveHandler(h) -> channel.AddReceiveHandlers(binding, h)
channel/v5 repurposes TypedReceiveHandler for the senders-typed handler and replaces the
self-describing pattern with ContentTypeReceiver plus the AddReceiveHandlers free function
(openziti/channel#262). Mechanical conversion; does not build on its own.
- moves the channel dependency to channel/v5 v5.0.10 and sdk-golang to v1.9.0 in the root and zititest modules
- mechanically rewrites every channel/v4 import path to channel/v5
This is the import-path-only step; the API-level changes the switch requires land in the following commit. This commit does not build on its own.
- invokes bind handlers via h.BindChannel(binding) instead of binding.Bind(h), which channel v5 removes from the Binding interface
- removes WithPriority from edge dial and state message sends; priority was already a no-op on grouped channels and channel v5 removes the priority API
- changes lastResponse from plain int64 to atomic.Int64 in both router
and peer heartbeat callbacks, fixing a data race between the heartbeat
response handler and the heartbeat check ticker
- fixes peer heartbeat logger channelType from "router" to "peer"
* Allow routers to request current cluster membership information. Fixes#3503
* Get cluster membership information from raft directly, rather than trying to cache it in the DB. Fixes#3501
* Set a router data model timeline when initializing a new HA setup, rather than letting it stay blank. Fixes#3500
* Reduce router data model full state updates. Fixes#3504
Quiesce marks all terminators as failed and stores the previous state.
Dequiesce restores all terminators with failed state and stored previous
state to their previous state
Adds config to controller for heartbeat config
Add config to routers for heartbeat config
Adds configurable heartbeats to controller <-> controller connections