mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-11 14:00:29 +00:00
52489e8926
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
41 lines
1.3 KiB
Go
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)
|
|
}
|
|
}
|