inputs

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package inputs assembles one Wavefront evaluation from live cluster state: discovery, selector-overlap detection, source resolution, graph derivation and the engine evaluation over them.

It is read-only and side-effect free — no writes, no events, no metrics, no poller — so the reconciler and the CLI derive the *same* picture from the same reads: the reconciler adds execution, status and telemetry on top, while the CLI renders the Result directly. Every pass is a full recalculation from live inputs; nothing here reads back previously published status.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Capped

func Capped[T any](list []T) []T

Capped bounds an exceptional-state list; the counts stay authoritative.

func HeldSources

func HeldSources(res *Result) []wavefrontv1alpha1.HeldNode

HeldSources builds the capped, source-sorted hold ledger. It is the ONE list: consumers write exactly this to status.held and edge-trigger against exactly this, so the ledger written and the ledger diffed are byte-identical. A source beyond StatusListCap is counted in status.Nodes.Held but neither listed nor announced until a freed slot promotes it into the cap.

Types

type GraphVerdict

type GraphVerdict struct {
	Valid   bool
	Reason  string
	Message string
}

GraphVerdict is the structural verdict on one pass: the GraphValid condition in all but name.

type Hold

type Hold struct {
	Manager string
	Kind    HoldKind
}

Hold is one source's entry in the unified ledger that treats a hand-pin and a suspend alike: Manager is "" for a Suspend hold, which names no owning actor.

type HoldKind

type HoldKind string

HoldKind distinguishes how a source is held: a foreign field manager owning spec.ref.commit, or spec.suspend. Both are reported identically by the engine (NodeResult.Held, engine.go SelfHeld/AncestorHeld) and must be reported identically by consumers.

type Params

type Params struct {
	Wavefront *wavefrontv1alpha1.Wavefront
	Adapter   adapter.Adapter
	Strategy  selection.Strategy
	// Observations is the caller's own coherent snapshot of the poller; nil
	// (or a missing entry) means unobserved. Strict ordering for co-arriving
	// changes is only structural if every node is evaluated against the same
	// sweep, so the snapshot is taken by the caller — once, before anything
	// reconfigures the poller — never re-read per source here.
	Observations map[types.NamespacedName]gitpoll.Observation
}

Params is everything Build needs beyond the cluster reader.

type Result

type Result struct {
	// discovery
	Nodes    map[adapter.NodeRef]adapter.Node // selected set plus dependsOn closure
	Selected map[adapter.NodeRef]bool
	Missing  map[adapter.NodeRef]bool // dependsOn targets that do not exist

	// source resolution
	Inputs map[adapter.NodeRef]engine.NodeInput
	Repos  map[types.NamespacedName]*sourcev1.GitRepository
	// NodeBySource lists every selected, pinned node referencing a source,
	// each slice in compareRefs order: a shared source's events and status
	// attribution need every referencing node, not just whichever last
	// overwrote a single value.
	NodeBySource map[types.NamespacedName][]adapter.NodeRef
	// Holds is the unified hold ledger: every source the engine reports Held
	// for, whether a hand-pin (a foreign field manager owns spec.ref.commit)
	// or a suspend (spec.suspend). It feeds counts.Held, status.held[], the
	// HoldDetected/HoldReleased edge-trigger and the admission gate alike. A
	// caller that discovers a further hold while executing (an SSA conflict,
	// pin.ErrHeld) may add to it after Build returns.
	Holds   map[types.NamespacedName]Hold
	Targets []gitpoll.Target
	// UnsupportedSources lists managed sources whose ref style (currently:
	// semver tracking, which only a future SemverWindow strategy could
	// sequence) selection.TrackRef cannot resolve, demoted to gates.
	// Recorded once per source and sorted, so a caller can announce each
	// exactly once.
	UnsupportedSources []types.NamespacedName

	// fleet
	Wavefronts *wavefrontv1alpha1.WavefrontList
	Overlap    string // name of the Wavefront whose selector overlaps this one

	// graph and evaluation
	Graph  *graph.Graph
	Cycles [][]adapter.NodeRef
	Eval   engine.Evaluation

	// Resolved and GraphChecked record how far the pass got: an aborted pass
	// has proven nothing about the fleet (Resolved false) and, before
	// derivation, nothing about the graph either (GraphChecked false).
	Resolved     bool
	GraphChecked bool
}

Result is one pass's complete read-only derivation.

It is returned non-nil even when Build fails, so a caller can still report whatever the pass managed to prove: Resolved and GraphChecked record how far it got, and every consumer must respect them rather than mistake a partial Result for a proven-empty fleet.

func Build

func Build(ctx context.Context, r client.Reader, p Params) (*Result, error)

Build performs one full read-only pass: discovery, overlap detection, source resolution, graph derivation and evaluation.

The Result is always non-nil, populated as far as the pass got, even when an error is returned.

func (*Result) GraphVerdict

func (res *Result) GraphVerdict() GraphVerdict

GraphVerdict renders the structural verdict. A selector overlap outranks a cycle: overlap suppresses admissions fleet-wide and is the more urgent configuration error to report.

func (*Result) SkipAdmissions

func (res *Result) SkipAdmissions() bool

SkipAdmissions reports whether every write must be suppressed for the pass, without suppressing status: selector overlap is a configuration error, not a reason to go blind.

type Summary

type Summary struct {
	Counts wavefrontv1alpha1.NodeCounts
	Phase  wavefrontv1alpha1.Phase
	// Blocked and Held are the capped status lists; Held is exactly
	// HeldSources(res): the same capped, source-sorted list that both becomes
	// status.held and is diffed pass-to-pass to edge-trigger the
	// HoldDetected/HoldReleased events, rather than an unbounded internal
	// ledger.
	Blocked []wavefrontv1alpha1.BlockedNode
	Held    []wavefrontv1alpha1.HeldNode
	// Members is every evaluated node's derived state, sorted by
	// kind/namespace/name and capped at MembersCap; MembersOmitted counts the
	// remainder. Write-only output: nothing here or in the reconciler ever
	// reads it back — admissibility is re-derived from live cluster state on
	// every pass, never from a previous status write.
	Members        []wavefrontv1alpha1.Member
	MembersOmitted int
	// BlockedByReason is uncapped, unlike Blocked: a gauge must count every
	// blocked node, not just the ones that fit the status list.
	BlockedByReason map[engine.BlockedReason]int
	FetchFailures   int
}

Summary is the whole publishable picture of one resolved pass: everything status carries, plus the uncapped by-reason tallies a caller may want for gauges. Deriving it here rather than in the reconciler is what lets the CLI re-derive byte-identical numbers from the same Result: summarisation is a pure function of the already-resolved evaluation, with no hidden state of its own to diverge from a live pass.

func Summarise

func Summarise(res *Result, now time.Time) Summary

Summarise derives the fleet counts, exceptional-state lists, members and phase from a completed evaluation. now supplies the fallback timestamp for a blocked node with no observation of its own; it is never used to make a decision, so a caller's clock choice cannot change what is reported.

Callers must only call this for a resolved Result: an aborted pass has derived nothing, and its zero values would claim a settled, empty fleet.

Jump to

Keyboard shortcuts

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