R-1252 (P2): a rejected or absent backup block never deletes second-drive copies — reconcile only on a valid classification; a rejected block is said on the app's status and once a day to the operator (backup_run_failures); kept copies stay kept (H2); Remove drops the kept records it deleted (H9). Commit only.
gates / gates (push) Successful in 1m18s
gates / gates (push) Successful in 1m18s
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package backup
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// R-1252 (review round 2, HUNT-2 H1): a rejected backup block never deletes second-drive copies. RunTier2 reconciles
|
||||
// only on a valid classification (tier2CaptureSetFull's `classified`); for a REJECTED block it says so on the app's
|
||||
// status (note.tier2.settings_unreadable_kept) and tells the operator once a day through the existing operator-only
|
||||
// digest (backup_run_failures, leg tier2-settings-unreadable — no new event type, so no hub change). Pinned by
|
||||
// r1252_rejected_block_keeps_copies_test.go.
|
||||
|
||||
type tier2UnreadableWatch struct {
|
||||
mu sync.Mutex
|
||||
notify func(app, why string)
|
||||
sent map[string]string // app → the UTC day it was last sent
|
||||
now func() time.Time
|
||||
}
|
||||
|
||||
// SetTier2SettingsUnreadableNotify wires the operator signal (main.go → notifier). INIT-ONLY.
|
||||
func (m *Manager) SetTier2SettingsUnreadableNotify(fn func(app, why string)) {
|
||||
m.tier2Unreadable.mu.Lock()
|
||||
m.tier2Unreadable.notify = fn
|
||||
m.tier2Unreadable.mu.Unlock()
|
||||
}
|
||||
|
||||
// backupBlockRejected asks the stack provider why the app's backup block was rejected ("" = valid or absent).
|
||||
func (m *Manager) backupBlockRejected(stack string) string {
|
||||
if r, ok := m.stackProvider.(interface{ BackupBlockRejected(string) string }); ok {
|
||||
return r.BackupBlockRejected(stack)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// notifyTier2SettingsUnreadable sends the operator signal at most once per app per UTC day.
|
||||
func (m *Manager) notifyTier2SettingsUnreadable(app, why string) {
|
||||
w := &m.tier2Unreadable
|
||||
w.mu.Lock()
|
||||
now := time.Now
|
||||
if w.now != nil {
|
||||
now = w.now
|
||||
}
|
||||
day := now().UTC().Format("2006-01-02")
|
||||
if w.notify == nil || w.sent[app] == day {
|
||||
w.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if w.sent == nil {
|
||||
w.sent = map[string]string{}
|
||||
}
|
||||
w.sent[app] = day
|
||||
fn := w.notify
|
||||
w.mu.Unlock()
|
||||
fn(app, why)
|
||||
}
|
||||
Reference in New Issue
Block a user