Files
pulse/internal/monitoring/monitor_planned_interval_test.go
T
rcourtman 52489e8926 Scale connection stale cutoff by the adaptive planned poll interval
Adaptive polling deliberately stretches an instance's cadence toward its
max interval (5 minutes by default) while data is fresh, but the
connections aggregator judged staleness against the configured cadence
with a 2-minute floor. Any adaptive-enabled install therefore cycled
healthy PVE/PBS/PMG connections into stale for the back half of every
stretched poll gap: the Infrastructure page dropped the source badge
from API + Agent to Agent and connection-degraded alerts fired against
a schedule the poller was honoring.

The aggregator now scales the active-to-stale cutoff by the scheduler's
currently planned interval when that exceeds the configured cadence,
via Monitor.PlannedPollInterval and per-instance planned intervals in
the aggregator inputs. A plan tighter than the configured cadence never
tightens the cutoff, so genuine poll outages still trip the floor on
time. Connection-degraded alerts and the runtime inventory gate consume
the same derived state and inherit the fix.

Refs #1437

Contract-Neutral: behavioral fix: stale cutoff follows adaptive planned interval (#1437), no public contract delta
2026-08-11 14:05:06 +01:00

41 lines
1.3 KiB
Go

package monitoring
import (
"testing"
"time"
)
// PlannedPollInterval feeds the connections aggregator the cadence the
// adaptive scheduler actually promised, so the active→stale cutoff can track
// stretched schedules (#1437).
func TestPlannedPollIntervalReportsLastScheduled(t *testing.T) {
sched := NewAdaptiveScheduler(DefaultSchedulerConfig(), nil, nil, nil)
now := time.Now()
tasks := sched.BuildPlan(now, []InstanceDescriptor{{
Name: "pve-a",
Type: InstanceTypePVE,
LastSuccess: now,
}}, 0)
if len(tasks) != 1 {
t.Fatalf("planned tasks = %d, want 1", len(tasks))
}
if tasks[0].Interval <= 0 {
t.Fatalf("planned interval = %v, want > 0", tasks[0].Interval)
}
m := &Monitor{scheduler: sched}
if got := m.PlannedPollInterval(InstanceTypePVE, "pve-a"); got != tasks[0].Interval {
t.Fatalf("PlannedPollInterval = %v, want %v", got, tasks[0].Interval)
}
if got := m.PlannedPollInterval(InstanceTypePVE, "unknown"); got != 0 {
t.Fatalf("unknown instance interval = %v, want 0", got)
}
if got := (&Monitor{}).PlannedPollInterval(InstanceTypePVE, "pve-a"); got != 0 {
t.Fatalf("schedulerless monitor interval = %v, want 0", got)
}
var nilMonitor *Monitor
if got := nilMonitor.PlannedPollInterval(InstanceTypePVE, "pve-a"); got != 0 {
t.Fatalf("nil monitor interval = %v, want 0", got)
}
}