Documentation
¶
Overview ¶
Package reconciler implements the Reconciler component that triggers reconciliation events on resource changes.
The Reconciler is a Stage 5 controller component. It subscribes to resource change events and publishes a ReconciliationTriggeredEvent IMMEDIATELY for each one — there is no reconciler-level refractory/debounce. Batching of rapid changes happens upstream, per watched-resource kind (the pkg/k8s/watcher leading-edge debouncer; default 2s, EndpointSlice "0"), and reload throttling happens downstream (the deployer's minDeploymentInterval, which the runtime-eligible fast path bypasses). Keeping the reconciler immediate means a runtime-eligible endpoint change reaches the deployer with no latency added by this layer.
Index ¶
Constants ¶
const ( // CoordinatorComponentName is the unique identifier for the ReconciliationCoordinator. CoordinatorComponentName = "reconciliation-coordinator" // CoordinatorEventBufferSize is the size of the event subscription buffer. // ReconciliationTriggeredEvents are tiny (a reason string + correlation), // so a large buffer is cheap, and it must be large: under churn the // Reconciler fires one trigger per resource change and a StandardSubscriber- // Buffer (50) overflows, dropping triggers (and thus renders). The Start // loop drains this buffer to a single trigger per render (coalesceQueuedTriggers), // so it only ever needs to hold the triggers that arrive during one // render+validate cycle. CoordinatorEventBufferSize = busevents.DebugSubscriberBuffer )
const ComponentName = "reconciler"
ComponentName is the unique identifier for this component.
const EventBufferSize = busevents.HighVolumeSubscriberBuffer
EventBufferSize is the size of the event subscription buffer. High-volume component that receives resource change events from every configured watcher, sized to handle bursts when many resources change simultaneously.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Coordinator ¶
type Coordinator struct {
*component.ReadySignal
// contains filtered or unexported fields
}
Coordinator orchestrates reconciliation by calling the Pipeline directly.
Render and validate run synchronously inside Pipeline.Execute() (ADR-0001 — no event hop), and the Coordinator publishes the appropriate events for downstream consumers based on the result.
Flow:
- ReconciliationTriggeredEvent received
- Publish ReconciliationStartedEvent
- Call Pipeline.Execute() (renders and validates)
- If success: Publish TemplateRenderedEvent + ValidationCompletedEvent
- If failure: Publish ReconciliationFailedEvent
The DeploymentScheduler still operates event-driven, receiving TemplateRenderedEvent and ValidationCompletedEvent to schedule deployments.
func NewCoordinator ¶
func NewCoordinator(cfg *CoordinatorConfig) *Coordinator
NewCoordinator creates a new ReconciliationCoordinator.
Note: eventChan is NOT subscribed here - subscription happens in Start(). This is a leader-only component that subscribes when Start() is called (after leadership is acquired). All-replica components replay their state on BecameLeaderEvent to ensure leader-only components receive current state.
Parameters:
- cfg: Configuration for the coordinator
Returns:
- A new Coordinator instance ready to be started
func (*Coordinator) Name ¶
func (c *Coordinator) Name() string
Name returns the unique identifier for this component.
func (*Coordinator) Start ¶
func (c *Coordinator) Start(ctx context.Context) error
Start begins the coordinator's event loop.
This method blocks until the context is cancelled.
NOTE: deliberately NOT converted to embed component.Base. Base subscribes at construction, but the coordinator is a leader-only component whose input (ReconciliationTriggeredEvent) is published by the all-replica Reconciler on EVERY replica — a constructor-time subscription would have follower replicas fill the buffer and log critical drops continuously. Subscribing here, on leadership, keeps followers unsubscribed entirely.
type CoordinatorConfig ¶
type CoordinatorConfig struct {
// EventBus is the event bus for subscribing to events and publishing results.
EventBus *busevents.EventBus
// Pipeline is the render-validate pipeline to execute.
// Must implement PipelineExecutor interface.
Pipeline PipelineExecutor
// StoreProvider provides access to resource stores.
StoreProvider stores.StoreProvider
// Logger is the structured logger.
Logger *slog.Logger
}
CoordinatorConfig contains configuration for creating a Coordinator.
type PipelineExecutor ¶
type PipelineExecutor interface {
Execute(ctx context.Context, provider stores.StoreProvider) (*pipeline.PipelineResult, error)
}
PipelineExecutor defines the interface for executing the render-validate pipeline. This allows mocking in tests.
type Reconciler ¶
Reconciler triggers reconciliation immediately on every resource/HTTP change.
There is NO reconciler-level debounce. Rapid changes are batched upstream by the per-watcher debouncer (pkg/k8s/watcher), and reload-inducing structural deploys are throttled downstream by the deployer's minDeploymentInterval (which the runtime-eligible fast path skips). Firing immediately here ensures runtime-eligible endpoint changes (e.g. EndpointSlice watchers with debounceInterval: "0") propagate with no added latency. All trigger paths fire immediately:
- ResourceIndexUpdatedEvent → "resource_change"
- HTTPResourceUpdatedEvent → "http_resource_change"
- IndexSynchronizedEvent → "index_synchronized" (initial reconciliation)
- HTTPResourceAcceptedEvent / DriftPreventionTriggeredEvent / BecameLeaderEvent → immediate command triggers
The component publishes ReconciliationTriggeredEvent to signal the Coordinator to begin a reconciliation cycle. Coalescible state-update triggers (resource_change, http_resource_change) may be superseded downstream by a newer trigger; command triggers are always processed.
func New ¶
func New(eventBus *busevents.EventBus, logger *slog.Logger) *Reconciler
New creates a new Reconciler component.
Parameters:
- eventBus: The EventBus for subscribing to events and publishing triggers
- logger: Structured logger for component logging
Returns:
- A new Reconciler instance ready to be started
func (*Reconciler) HandleEvent ¶
func (r *Reconciler) HandleEvent(event busevents.Event)
HandleEvent implements component.EventHandler: it dispatches events to their handlers, tracking processing time for the health check. Each handler triggers reconciliation immediately — there is no reconciler-level debounce.
func (*Reconciler) HealthCheck ¶
func (r *Reconciler) HealthCheck() error
HealthCheck implements the lifecycle.HealthChecker interface. Returns an error if the component appears to be stalled (processing for > timeout). Returns nil when idle (not processing) - idle is always healthy for event-driven components.