Documentation
¶
Index ¶
Constants ¶
const DefaultInterval = 60 * time.Second
DefaultInterval is the default reconciliation interval.
Variables ¶
This section is empty.
Functions ¶
func NewStateSnapshot ¶
func NewStateSnapshot() *stateSnapshot
NewStateSnapshot returns a new, empty snapshot.
Types ¶
type Config ¶
type Config struct {
// Interval is the time between reconciliation cycles.
// Default: 60s
Interval time.Duration `yaml:"interval"`
}
Config holds the configuration for the reconciliation loop. Config is passed as a constructor argument — no file I/O in this package.
func (*Config) ApplyDefaults ¶
func (c *Config) ApplyDefaults()
ApplyDefaults sets default values for zero-valued fields.
type DispatchHandler ¶ added in v0.3.0
type DispatchHandler func(ctx context.Context, desired *api.NodeStateSnapshot)
DispatchHandler is a function invoked on every successful pull. Dispatch handlers consume the delivery-queue blocks of the snapshot (e.g. executions), which are not desired state to converge on. They return nothing: a dispatch problem is logged where it happens and must neither block the snapshot update nor count as a handler failure.
type ReachabilityObserver ¶ added in v0.7.0
type ReachabilityObserver struct {
// contains filtered or unexported fields
}
ReachabilityObserver logs the control plane's reachability verdict about this node whenever it changes. The verdict is the one signal a node cannot derive for itself: an agent whose state pulls succeed while its heartbeats stop being admitted looks healthy in its own journal and reads as stale or unreachable to everyone else. One line at the moment the verdict changes puts that split where a node operator already looks.
The block is a diagnostic projection, not desired state. The observer stores nothing beyond the last verdict it saw, and the snapshot store still never keeps the block.
A ReachabilityObserver is not safe for concurrent use. Handle is invoked only from the reconcile goroutine, one cycle at a time, so its fields need no mutex.
func NewReachabilityObserver ¶ added in v0.7.0
func NewReachabilityObserver(logger *slog.Logger) *ReachabilityObserver
NewReachabilityObserver returns an observer that logs verdict changes through logger.
func (*ReachabilityObserver) Handle ¶ added in v0.7.0
func (o *ReachabilityObserver) Handle(_ context.Context, desired *api.NodeStateSnapshot)
Handle observes the snapshot's reachability block. Its signature matches DispatchHandler, so it runs on every successful pull, including the cycles the empty-diff short-circuit ends early.
type ReconcileHandler ¶
type ReconcileHandler func(ctx context.Context, desired *api.NodeStateSnapshot, diff StateDiff) error
ReconcileHandler is a function invoked when drift is detected.
type Reconciler ¶
type Reconciler struct {
// contains filtered or unexported fields
}
Reconciler periodically compares desired state against a local snapshot and invokes registered handlers to correct drift.
func NewReconciler ¶
func NewReconciler(client StateFetcher, cfg Config, logger *slog.Logger) *Reconciler
NewReconciler creates a new Reconciler with the given configuration. Config defaults are applied automatically.
func (*Reconciler) RegisterDispatchHandler ¶ added in v0.3.0
func (r *Reconciler) RegisterDispatchHandler(handler DispatchHandler)
RegisterDispatchHandler adds a dispatch handler invoked on every successful pull, regardless of drift. Handlers are called in registration order. RegisterDispatchHandler must be called before Run; it is not safe for concurrent use.
func (*Reconciler) RegisterHandler ¶
func (r *Reconciler) RegisterHandler(handler ReconcileHandler)
RegisterHandler adds a reconciliation handler invoked on drift detection. Handlers are called in registration order. RegisterHandler must be called before Run; it is not safe for concurrent use.
func (*Reconciler) Run ¶
func (r *Reconciler) Run(ctx context.Context, nodeID string) error
Run starts the reconciliation loop. It blocks until ctx is cancelled. The first cycle runs immediately; subsequent cycles run at cfg.Interval or when TriggerReconcile is called.
func (*Reconciler) TriggerReconcile ¶
func (r *Reconciler) TriggerReconcile()
TriggerReconcile requests an immediate reconciliation cycle. Multiple rapid calls are coalesced — only one extra cycle runs.
type StateDiff ¶
type StateDiff struct {
PeersToAdd []api.SnapshotPeer
PeersToRemove []string // node IDs
PeersToUpdate []api.SnapshotPeer // peers with changed fields
PolicyChanged bool
BridgeChanged bool
StateChanged bool
ReportsChanged bool
}
StateDiff describes the drift between a desired NodeStateSnapshot (from the control plane) and the current locally-observed snapshot. The four block flags are presence-aware: a nil block and a populated block are distinct, so null on the wire ("not populated") drives convergence rather than a no-op.
func ComputeDiff ¶
func ComputeDiff(desired, current *api.NodeStateSnapshot) StateDiff
ComputeDiff compares the desired snapshot from the control plane against the current local snapshot and returns a StateDiff describing what has changed.
type StateFetcher ¶
type StateFetcher interface {
FetchState(ctx context.Context, nodeID string) (*api.NodeStateSnapshot, error)
}
StateFetcher retrieves the desired-state snapshot from the control plane.