0.2.66 - End Credits improvements / Gateway: 0.1.47 - End credits redesign

This commit is contained in:
ponzischeme89
2026-08-15 22:26:17 +12:00
parent e528d04b43
commit 4bc4b075ec
28 changed files with 643 additions and 211 deletions
+18 -11
View File
@@ -51,15 +51,21 @@ type Task struct {
// Status is one task as the console reads it: the declaration, the operator's overrides,
// the last run and when the next one is due.
type Status struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Group string `json:"group"`
Interval int64 `json:"intervalSeconds"`
Enabled bool `json:"enabled"`
Running bool `json:"running"`
NextRun *time.Time `json:"nextRun,omitempty"`
LastRun *store.TaskRun `json:"lastRun,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Group string `json:"group"`
Interval int64 `json:"intervalSeconds"`
// DefaultInterval is the cadence declared in code, which Interval hides whenever an
// operator has overridden it. Both are sent because the console cannot otherwise tell
// "every ten minutes because that is the default" from "every ten minutes because
// somebody chose it" — and without that distinction its cadence control has no way to
// offer a way back, or to say that a task is no longer running as shipped.
DefaultInterval int64 `json:"defaultIntervalSeconds"`
Enabled bool `json:"enabled"`
Running bool `json:"running"`
NextRun *time.Time `json:"nextRun,omitempty"`
LastRun *store.TaskRun `json:"lastRun,omitempty"`
}
type registered struct {
@@ -458,8 +464,9 @@ func (s *Scheduler) Snapshot() []Status {
status := Status{
ID: entry.task.ID, Name: entry.task.Name,
Description: entry.task.Description, Group: entry.task.Group,
Interval: int64(entry.effectiveInterval() / time.Second),
Enabled: entry.enabled, Running: entry.running,
Interval: int64(entry.effectiveInterval() / time.Second),
DefaultInterval: int64(entry.task.Interval / time.Second),
Enabled: entry.enabled, Running: entry.running,
}
if !entry.nextRun.IsZero() && entry.enabled {
next := entry.nextRun
@@ -219,3 +219,44 @@ func waitForRun(t *testing.T, sched *Scheduler, id string) Status {
}
var _ sync.Locker = (*sync.Mutex)(nil)
// The console needs both cadences to draw its control honestly: the one in force and the
// one the code declares. Reporting only the effective interval made "every ten minutes
// because that is the default" and "every ten minutes because somebody chose it" identical
// on the wire, so nothing could offer a way back to the default or mark a task as no longer
// running as shipped.
func TestSnapshotReportsTheDeclaredCadenceBesideTheEffectiveOne(t *testing.T) {
sched := quietScheduler()
sched.Register(Task{ID: "credits", Name: "Credits", Interval: 10 * time.Minute, Run: noop})
before := sched.Snapshot()[0]
if before.Interval != 600 || before.DefaultInterval != 600 {
t.Fatalf("unoverridden task: interval %d, default %d, want 600 and 600",
before.Interval, before.DefaultInterval)
}
if err := sched.SetInterval(context.Background(), "credits", time.Hour); err != nil {
t.Fatalf("SetInterval: %v", err)
}
after := sched.Snapshot()[0]
if after.Interval != 3600 {
t.Fatalf("effective interval %d, want 3600", after.Interval)
}
// The declared cadence must survive the override, or the way back is lost.
if after.DefaultInterval != 600 {
t.Fatalf("declared cadence %d, want 600 — an override must not overwrite it",
after.DefaultInterval)
}
}
// A task that declares no cadence at all runs only when somebody presses the button, and
// the console has to be able to say so rather than printing "every 0 seconds".
func TestATaskWithNoDeclaredCadenceReportsZeroForBoth(t *testing.T) {
sched := quietScheduler()
sched.Register(Task{ID: "manual", Name: "Manual", Run: noop})
status := sched.Snapshot()[0]
if status.Interval != 0 || status.DefaultInterval != 0 {
t.Fatalf("interval %d, default %d, want 0 and 0", status.Interval, status.DefaultInterval)
}
}