Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v1.3.104 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package store pkg/deployment/rf/store/finder.go c2-net-routing

Package store pkg/deployment/rf/store/graph_cache.go c2-net-routing

Package store pkg/deployment/rf/store/graph_full.go c2-net-routing

Package store pkg/deployment/rf/store/landmark.go c2-net-routing

Landmark (transit-node) routing for the route-finder. The base route-finder answers each (src,dst) with a bounded but EXHAUSTIVE BFS over the whole dense transport graph; on the live network a single far/hard pair has been measured at ~8.4s of CPU and pegs the RF host. #4380 (cached graph) and #4385 (per-graph result memo) removed the per-request graph BUILD and the REPEAT BFS, but the first search of any pair is still exhaustive.

This exploits the mesh's structure: a handful of very-high-degree hubs (magnetosphere/prod02/the production exit carry ~1200-1300 transports each vs ~70-120 for a normal node) that most routes already transit, plus deterministic tpids and durable topology (see rf-landmark-routing-rfc.md). We precompute routes between every node and those hubs ONCE per graph, then answer a far (src,dst) by COMPOSING src->hub + hub->dst — ~H*K*K cheap concatenations instead of a graph-wide search.

It is a strict addition: a pair the (budget-bounded) direct BFS resolves cheaply keeps its optimal exhaustive answer; only the pairs that blow past the budget — the multi-second cases that peg the RF — fall to composition, and a composition miss still falls through to the full BFS. Coexists with #4380 and #4385 (the memo caches composed results exactly as it caches BFS results).

Package store pkg/deployment/rf/store/mark_and_sweep.go c2-net-routing

Index

Constants

View Source
const DefaultCacheRefresh = 15 * time.Second

DefaultCacheRefresh is how old the graph may get before a request triggers a rebuild, when none is given.

View Source
const DefaultMaxBFSQueue = 200000

DefaultMaxBFSQueue is the default per-call BFS queue cap when the caller of StreamRoutesWithCap passes 0 / negative. Conservative enough to fit comfortably on a CLI/visor without OOMing dense networks at high --max.

View Source
const HopLatencyPenaltyMS = 500.0

HopLatencyPenaltyMS is the latency assumed for a transport that has no measured latency. It keeps latency-weighted routing usable when data is missing: an unmeasured edge is treated as worse than a typical measured one (so measured low-latency edges win), and a route of all-unmeasured edges is effectively ranked by hop count (number of hops × penalty) — degrading to the legacy behavior rather than treating missing data as free.

Variables

View Source
var (
	//ErrNoRoute no route to destination
	ErrNoRoute = errors.New("no route to destination")
	//ErrContextClosed context closed or timed out
	ErrContextClosed = errors.New("context closed or timed out")
	//ErrRouteNotFound route not found
	ErrRouteNotFound = errors.New("route not found")
)
View Source
var MaxGraphDepth = 10

MaxGraphDepth limits how deep the graph exploration goes from the root. This prevents OOM on large networks. Used as default by NewGraph.

Functions

func SetLandmarkRouting

func SetLandmarkRouting(on bool)

SetLandmarkRouting turns landmark routing on or off for every graph.

Types

type Graph

type Graph struct {
	// contains filtered or unexported fields
}

Graph represents a visor's connections graph (skywire network)

func NewFullGraph

func NewFullGraph(ctx context.Context, s store.Store) (*Graph, error)

func NewGraph

func NewGraph(ctx context.Context, s store.Store, rootPK cipher.PubKey) (*Graph, error)

NewGraph creates a new Graph accessing given transport store, such Graph is created by exploring from rootPK cipher PubKey. Uses MaxGraphDepth for depth limiting.

func NewGraphWithDepth

func NewGraphWithDepth(ctx context.Context, s store.Store, rootPK cipher.PubKey, maxDepth int) (*Graph, error)

NewGraphWithDepth creates a new Graph with an explicit depth limit for exploration.

func (*Graph) GetRoute

func (g *Graph) GetRoute(ctx context.Context, source, destination cipher.PubKey, minLen, maxLen, number int) ([]routing.Route, error)

GetRoute returns routes from source to destination with hop counts within [minLen, maxLen], prioritized by shortest hop count first, with no duplicate vertices in the route.

Bounded variant: stops the BFS as soon as `number` valid routes have been collected. Use StreamRoutes for the unbounded streaming form when memory matters more than the convenience of a slice.

func (*Graph) GetRouteWeighted

func (g *Graph) GetRouteWeighted(ctx context.Context, source, destination cipher.PubKey, minLen, maxLen, number int, byLatency bool) ([]routing.Route, error)

GetRouteWeighted returns up to `number` routes source→destination, memoized per Graph. The exhaustive BFS over the (dense) transport graph is expensive — seconds per request for well-connected pairs — and the fleet re-asks for the same pairs constantly (session churn), so without a cache the route-finder re-runs an identical search on every repeat. The memo collapses those to one BFS per unique request for the life of this graph, and its sync.Once also deduplicates a concurrent thundering herd of identical requests into a single search rather than N. Failures are not cached (the entry is dropped) so a transient miss can be retried immediately; only successful route sets persist, until the next graph rebuild swaps in a fresh (empty) memo. Callers must treat the returned slice as read-only.

func (*Graph) MarkAndSweep

func (g *Graph) MarkAndSweep(ctx context.Context, rootPK cipher.PubKey) ([]cipher.PubKey, error)

MarkAndSweep explores the Graph again from rootPK. It returns the now unreachable nodes pks by comparing with the previous Graph

func (*Graph) Size added in v1.3.100

func (g *Graph) Size() (visors, transports int)

Size is how many visors the graph holds and how many transports join them.

func (*Graph) StreamRoutes

func (g *Graph) StreamRoutes(ctx context.Context, source, destination cipher.PubKey, minLen, maxLen int, onRoute func(routing.Route) bool) error

StreamRoutes is the streaming form of GetRoute: it yields each valid path as soon as the BFS finds it, by invoking onRoute. Returning false from onRoute stops the search.

Equivalent to StreamRoutesWithCap with the default queue cap.

func (*Graph) StreamRoutesWithCap

func (g *Graph) StreamRoutesWithCap(ctx context.Context, source, destination cipher.PubKey, minLen, maxLen, queueCap int, onRoute func(routing.Route) bool) error

StreamRoutesWithCap is StreamRoutes with an explicit per-call queue cap. queueCap <= 0 means unbounded (use with caution; dense graphs at high maxLen can OOM).

BFS naturally explores by increasing hop length, so paths are emitted in shortest-first order — no post-search sort is needed, and the caller can stop after collecting enough short paths without paying for deeper exploration.

Memory: the working set is the BFS queue + the path being emitted; we never accumulate every valid path. The queue itself is capped by queueCap, so even count=0 (unbounded) requests have a hard memory ceiling. When the cap is hit, neighbor expansion is suppressed — already-queued paths still drain and emit, but new branches are dropped, so coverage degrades while the process stays alive.

func (*Graph) Sweep

func (g *Graph) Sweep() []cipher.PubKey

Sweep checks which nodes cannot be reached in the Graph and prepares for next iteration

type GraphCache

type GraphCache struct {
	// contains filtered or unexported fields
}

GraphCache holds ONE full-network graph, shared across every route request. This removes the per-request, per-source graph construction the route-finder did before — a redis walk that issued a GetTransportsByEdge for every node it discovered from the source, which pegged both the route-finder and redis under load. The cached graph is read-only during a BFS (StreamRoutes never mutates it), so many requests can share it concurrently; a rebuild constructs a fresh graph and swaps the pointer atomically, leaving in-flight requests on the previous one until they finish.

Once started, the graph is rebuilt when a request finds it older than the refresh interval, not on a timer. Rebuilding every 15 s over 93k transports while serving about 10 queries a minute was most of the route finder's CPU and allocation (audit 2026-10-16). A request that finds the graph stale is answered from it while one rebuild runs in the background; only a graph older than staleAfter is rebuilt before answering, so an idle route finder does not route on an old graph.

func NewGraphCache

func NewGraphCache(s store.Store, refresh time.Duration, log logrus.FieldLogger) *GraphCache

NewGraphCache returns an unstarted cache. Call Run (usually in a goroutine) to build it and let requests keep it fresh, or Rebuild once for a synchronous build. Until the first build completes Get returns nil and callers should fall back to a per-request build.

func (*GraphCache) Current

func (c *GraphCache) Current() *Graph

Current returns the graph as last built, never rebuilding it.

func (*GraphCache) Get

func (c *GraphCache) Get() *Graph

Get returns the current full graph, or nil before the first build. On a started cache a graph older than the refresh interval is rebuilt: in the background, or first when it is older than staleFactor intervals.

func (*GraphCache) Rebuild

func (c *GraphCache) Rebuild(ctx context.Context) (*Graph, error)

Rebuild reads the transport set once and swaps in a freshly built full graph. On a read error the previous graph is kept and the error returned.

func (*GraphCache) Run

func (c *GraphCache) Run(ctx context.Context)

Run builds the graph immediately and starts the cache: from then on requests rebuild it when stale (see Get), until ctx is done. A failed initial build is logged, and the next request tries again.

func (*GraphCache) ShareFrom added in v1.3.99

func (c *GraphCache) ShareFrom(url string)

ShareFrom makes the cache build from the live transport set of a TPD in this process that writes to the redis at url, when there is one — no redis read per rebuild. Call before Run.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL