controller v0.178.0 — R-88 Part 2: only a positive 'never' fires the valve
MinAgent: 0.105.0. scheduledRunAllowed fired on any nil age; it now requires a licence from valveLicensed, which grants it for AgeStateAbsent and for a LEGACY agent, and refuses it for AgeStateUnknown. An unreadable storage no longer masquerades as a first-ever backup and no longer quiesces apps outside the window. A missing wire field means legacy, not unknown — deliberately. Treating it as unknown would stop the valve firing on un-upgraded boxes and starve genuinely new ones. Degrade logged once; unrecognised future values also map to legacy. Caught in passing: TieredBackend is satisfied by a RUNTIME assertion, so the signature change compiled and vetted clean while quiesceBackend silently stopped satisfying it — which would have degraded every box to the single-tier path with no error. Added a compile-time witness. Also corrects the notifier comment that claimed operator-only came from a missing customerMessages entry; enforcement is hub-side operatorOnlyEvents (hub 0.79.0).
This commit is contained in:
@@ -28,15 +28,15 @@ import (
|
||||
// tierBackend is a multi-tier fake agent. phases[target] is the phase sequence returned by
|
||||
// successive BackupStatusFor calls for that tier.
|
||||
type tierBackend struct {
|
||||
mu sync.Mutex
|
||||
tiers []BackupTier
|
||||
tiersErr error
|
||||
dueSet map[string]bool
|
||||
phases map[string][]string
|
||||
phaseIdx map[string]int
|
||||
started []string // targets StartBackupFor/StartBackup was called with, in order
|
||||
mu sync.Mutex
|
||||
tiers []BackupTier
|
||||
tiersErr error
|
||||
dueSet map[string]bool
|
||||
phases map[string][]string
|
||||
phaseIdx map[string]int
|
||||
started []string // targets StartBackupFor/StartBackup was called with, in order
|
||||
untargetedDue bool
|
||||
startErrOn string
|
||||
startErrOn string
|
||||
// stacks (optional) lets a start sample how many restarts have happened SO FAR — the direct
|
||||
// way to assert "the app had not resumed when this tier started".
|
||||
stacks *fakeStacks
|
||||
@@ -55,10 +55,12 @@ func (b *tierBackend) Tiers(context.Context) ([]BackupTier, error) {
|
||||
}
|
||||
return b.tiers, nil
|
||||
}
|
||||
func (b *tierBackend) DueFor(_ context.Context, target string) (bool, *int64, error) {
|
||||
// DueFor returns a nil age with an EMPTY age_state — i.e. the pre-v0.105.0 (legacy) shape, which
|
||||
// keeps every suite written before R-88 Part 2 asserting exactly the behaviour it always did.
|
||||
func (b *tierBackend) DueFor(_ context.Context, target string) (bool, *int64, string, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
return b.dueSet[target], nil, nil
|
||||
return b.dueSet[target], nil, "", nil
|
||||
}
|
||||
func (b *tierBackend) StartBackupFor(_ context.Context, target string) (string, error) {
|
||||
b.mu.Lock()
|
||||
@@ -360,9 +362,9 @@ type dueErrBackend struct {
|
||||
errOn string
|
||||
}
|
||||
|
||||
func (d *dueErrBackend) DueFor(ctx context.Context, target string) (bool, *int64, error) {
|
||||
func (d *dueErrBackend) DueFor(ctx context.Context, target string) (bool, *int64, string, error) {
|
||||
if target == d.errOn {
|
||||
return false, nil, fmt.Errorf("simulated due-check failure")
|
||||
return false, nil, "", fmt.Errorf("simulated due-check failure")
|
||||
}
|
||||
return d.tierBackend.DueFor(ctx, target)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user