Documentation
¶
Overview ¶
Package scaling provides the policy engine for adaptive worker scaling. The policy evaluates system and pool metrics and produces scaling decisions; it does not execute them. Separation keeps the logic testable in isolation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Validate ¶
func Validate(cfg PolicyConfig) error
Validate checks that cfg contains internally consistent values.
Types ¶
type Autoscaler ¶
type Autoscaler struct {
// contains filtered or unexported fields
}
Autoscaler is a long-running goroutine that periodically evaluates the scaling policy and applies the resulting decision to the pool. Start it with Run(ctx) and cancel the context to shut it down.
func NewAutoscaler ¶
func NewAutoscaler(policy *ThresholdPolicy, pool PoolScaler, collector SystemCollector, logger *zap.Logger) *Autoscaler
NewAutoscaler creates an Autoscaler wired to the given policy, pool, and system collector. Scaling events are stored in an internal rolling buffer (capacity 100) accessible via Events(). Call SetPersister to additionally write events to durable storage.
func (*Autoscaler) Events ¶
func (a *Autoscaler) Events() []models.ScalingEvent
Events returns recent scaling events from the in-memory buffer, newest first.
func (*Autoscaler) PolicyConfig ¶
func (a *Autoscaler) PolicyConfig() PolicyConfig
PolicyConfig returns the policy configuration used by this autoscaler.
func (*Autoscaler) Run ¶
func (a *Autoscaler) Run(ctx context.Context) error
Run starts the evaluation loop. It blocks until ctx is cancelled, then returns ctx.Err(). The loop evaluates the policy at the configured interval and applies any non-Hold decision to the pool.
func (*Autoscaler) SetControlReader ¶
func (a *Autoscaler) SetControlReader(r ScalingControlReader)
SetControlReader attaches an optional store for reading manual scaling overrides. When set, the autoscaler checks for pause/set commands before each evaluation.
func (*Autoscaler) SetPersister ¶
func (a *Autoscaler) SetPersister(p EventPersister)
SetPersister attaches an optional durable store for scaling events. When set, each scale event is also saved via p.SaveScalingEvent so events survive process restarts and are visible to other processes (e.g. serve).
type Decision ¶
type Decision struct {
// Action is the recommended scaling action.
Action Action
// Delta is the number of workers to add (ScaleUp) or remove (ScaleDown).
// Zero for Hold decisions.
Delta int
// Reason is a human-readable explanation suitable for logs and the dashboard.
Reason string
// Confidence is a 0–1 score reflecting how many signals agree.
// Higher means more signals agree; lower means ambiguous.
Confidence float64
}
Decision is the output of a policy evaluation.
type EventBuffer ¶
type EventBuffer struct {
// contains filtered or unexported fields
}
EventBuffer is a fixed-capacity ring buffer of ScalingEvents. Oldest events are dropped when the buffer is full. All methods are safe for concurrent use.
func NewEventBuffer ¶
func NewEventBuffer(maxLen int) *EventBuffer
NewEventBuffer creates an EventBuffer with the given maximum capacity. If maxLen <= 0, it defaults to 100.
func (*EventBuffer) Add ¶
func (b *EventBuffer) Add(e models.ScalingEvent)
Add appends an event to the buffer. If the buffer is at capacity the oldest event is evicted to make room.
func (*EventBuffer) Events ¶
func (b *EventBuffer) Events() []models.ScalingEvent
Events returns a copy of all stored events in newest-first order.
type EventPersister ¶
type EventPersister interface {
SaveScalingEvent(ctx context.Context, e models.ScalingEvent) error
}
EventPersister is an optional interface for durable event storage. store.SQLiteStore satisfies this interface when scaling_events are enabled.
type Policy ¶
type Policy interface {
Evaluate(pool metrics.PoolSnapshot, sys metrics.SystemSnapshot) Decision
}
Policy evaluates metrics and returns a scaling Decision.
type PolicyConfig ¶
type PolicyConfig struct {
// Enabled controls whether the policy produces non-Hold decisions.
// When false, Evaluate always returns Hold.
Enabled bool `yaml:"enabled"`
// MinWorkers is the minimum worker count the policy will recommend.
MinWorkers int `yaml:"min_workers"`
// MaxWorkers is the maximum worker count the policy will recommend.
MaxWorkers int `yaml:"max_workers"`
// EvaluationInterval is a hint for the autoscaler loop; not enforced here.
EvaluationInterval time.Duration `yaml:"evaluation_interval"`
// CooldownAfterScale is the minimum time between consecutive scale events.
// Prevents oscillation.
CooldownAfterScale time.Duration `yaml:"cooldown_after_scale"`
// ScaleUp holds the scale-up thresholds.
ScaleUp ScaleUpConfig `yaml:"scale_up"`
// ScaleDown holds the scale-down thresholds.
ScaleDown ScaleDownConfig `yaml:"scale_down"`
}
PolicyConfig holds all configurable thresholds for ThresholdPolicy.
func DefaultPolicyConfig ¶
func DefaultPolicyConfig() PolicyConfig
DefaultPolicyConfig returns a conservative default configuration.
func LoadConfigFile ¶
func LoadConfigFile(path string) (PolicyConfig, error)
LoadConfigFile reads a YAML config file and returns the scaling policy configuration. If the file does not exist, DefaultPolicyConfig is returned. CLI flag overrides should be applied by the caller after this call.
type PoolScaler ¶
type PoolScaler interface {
Snapshot() metrics.PoolSnapshot
AddWorkers(n int) error
RemoveWorkers(n int) int
Workers() int
}
PoolScaler is the interface the autoscaler uses to inspect and resize the pool. agent.Pool satisfies this interface.
type ScaleDownConfig ¶
type ScaleDownConfig struct {
// IdleWorkerThreshold is the minimum number of idle workers required to consider
// scaling down.
IdleWorkerThreshold int `yaml:"idle_worker_threshold"`
// IdleDuration is how long idle workers must exceed IdleWorkerThreshold before
// scale-down is triggered. Prevents premature scale-down during brief lulls.
IdleDuration time.Duration `yaml:"idle_duration"`
}
ScaleDownConfig holds scale-down thresholds.
type ScaleUpConfig ¶
type ScaleUpConfig struct {
// MemoryThreshold is the maximum memory-usage percentage (heap/sys*100) below
// which scale-up is permitted. Protects against scaling under memory pressure.
MemoryThreshold int `yaml:"memory_threshold"`
// QueueDepthTrigger is the minimum queue depth that triggers a scale-up check.
QueueDepthTrigger int `yaml:"queue_depth_trigger"`
// AllWorkersBusy, when true, requires all workers to be active before scaling up.
AllWorkersBusy bool `yaml:"all_workers_busy"`
}
ScaleUpConfig holds scale-up thresholds.
type ScalingControlReader ¶
type ScalingControlReader interface {
GetScalingControl(ctx context.Context) (*models.ScalingControl, error)
}
ScalingControlReader reads the current manual scaling override. store.Store satisfies this interface.
type ScalingEvent ¶
type ScalingEvent = models.ScalingEvent
ScalingEvent is an alias for the shared models type. All code within this package uses models.ScalingEvent so callers share one type.
type SystemCollector ¶
type SystemCollector interface {
Collect() metrics.SystemSnapshot
}
SystemCollector provides runtime system snapshots. metrics.SystemCollector satisfies this interface.
type ThresholdPolicy ¶
type ThresholdPolicy struct {
// contains filtered or unexported fields
}
ThresholdPolicy is a Policy implementation driven by configurable thresholds. It is safe for concurrent use.
func NewThresholdPolicy ¶
func NewThresholdPolicy(cfg PolicyConfig) *ThresholdPolicy
NewThresholdPolicy creates a ThresholdPolicy with the given configuration. Invalid values are silently clamped to safe defaults (min/max bounds).
func (*ThresholdPolicy) Evaluate ¶
func (p *ThresholdPolicy) Evaluate(pool metrics.PoolSnapshot, sys metrics.SystemSnapshot) Decision
Evaluate returns the recommended scaling decision given current metrics. It considers queue depth, worker utilisation, memory pressure, idle duration, and the cooldown period.
func (*ThresholdPolicy) NotifyScaled ¶
func (p *ThresholdPolicy) NotifyScaled()
NotifyScaled records the time of a scale event for cooldown tracking. The autoscaler calls this after it applies a decision.