supervisor

package
v1.3.3 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package supervisor reconciles desired configuration (the store) against running source/sink/connector components.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RollupHealth

func RollupHealth(statuses []Status) string

RollupHealth reduces a set of component statuses (as returned by Supervisor.Statuses / config.Service.Statuses) to a single overall health string: "ok" when every component's State is "up" (including the empty set — a fresh, unconfigured system is healthy), "degraded" if any component is in any other state. Shared by the admin server's top-level GET /health (internal/app) and the config API's GET /api/v1/health (internal/api) so the two surfaces can never drift on this logic.

Types

type Status

type Status struct {
	Kind  string `json:"kind"`
	ID    string `json:"id"`
	State string `json:"state"` // "up" | "degraded" | "error"
	Err   string `json:"err,omitempty"`
}

type Supervisor

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

Supervisor reconciles desired configuration (read from the store) against running source/sink/connector components: starting, stopping, and restarting them to converge. Reconcile is safe to call repeatedly (idempotent when nothing changed) and safe to call concurrently: the whole operation — including the store read — runs under reconcileMu, so overlapping Reconcile calls fully serialize rather than racing a stale read against a newer one. Component constructors (source.New, sink.New, connector.Start) are expected to connect/dial asynchronously and return quickly.

Lock discipline: reconcileMu serializes the bodies of Reconcile and Stop (so they never interleave), including component construction and teardown. The sources/sinks/connectors/errored maps are guarded separately by stateMu, which is never held across constructors or Stop calls. Statuses() only needs stateMu, so it never blocks behind a slow Reconcile teardown or Stop.

Components started by Reconcile run on the Supervisor's own background context (runCtx below), NOT the context passed into Reconcile. runCtx is created in New and cancelled in Stop. This matters because Reconcile will eventually be invoked from HTTP handlers (hot config apply): if started components inherited that request-scoped context, they would be killed the moment the triggering HTTP request ended. Reconcile's ctx therefore only bounds the reconcile operation itself — the store read and the constructor calls — never a running component's lifetime.

Once Stop has run, runCtx is permanently cancelled (it is never recreated), so a later Reconcile call is a deliberate no-op (stopped below) rather than silently starting components bound to a dead context that would report as running but never actually do anything.

func New

func New(st *store.Store, busMgr *bus.Manager, ds *sink.DataServer, log *slog.Logger, met *metrics.Set, reg *stats.Registry) *Supervisor

func (*Supervisor) BusDevices

func (s *Supervisor) BusDevices() []bus.DeviceInfo

BusDevices returns every NMEA-2000 device currently observed across the running CAN endpoints (empty when no CAN bus is configured or connected). n2k v0.3.0's client tracks these automatically from address-claim traffic, so this is a free read once a bus client is up.

func (*Supervisor) BusStatuses

func (s *Supervisor) BusStatuses() []bus.EndpointStatus

BusStatuses returns bounded queue, subscription, lifecycle, and address- claim state for every running shared n2k client.

func (*Supervisor) Reconcile

func (s *Supervisor) Reconcile(ctx context.Context) (retErr error)

Reconcile diffs desired config (the store) against running components and converges: stop-then-start whatever changed. It returns an error when desired state cannot be loaded, fully validated, or have its process-wide resource budget applied; individual component failures are recorded as error statuses (see Statuses) and never abort or crash the reconcile.

func (*Supervisor) Statuses

func (s *Supervisor) Statuses() []Status

Statuses reports the current state of every running or errored component, for /health. It snapshots runtime references and stored errors under stateMu, then releases the lock before invoking component State methods. State may need an implementation-local lock (for example a file sink can be flushing), and that work must not prevent Reconcile or Stop from updating the supervisor maps. Runtime implementations support State racing with Stop.

func (*Supervisor) Stop

func (s *Supervisor) Stop()

Stop stops every running component (connectors, then sinks, then sources) and cancels the Supervisor's background context. Safe to call more than once. After Stop, Reconcile becomes a permanent no-op (see the Supervisor doc comment). Like Reconcile, the map mutation is done under stateMu but the actual (potentially slow) Stop() calls run outside stateMu so Statuses() never blocks behind shutdown either.

Jump to

Keyboard shortcuts

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