Operator actions in the report reply (D1, R-314/R-279/R-177, decision 185)
The hub may ask the running controller for a CLOSED list of actions, carried in the report ACK (operator_actions) and answered on the next report (operator_action_results): offsite_backup_now, abandon_stop, abandon_extend (1-30 days), run_job (fill-watch, offsite-integrity, offsite-proof, disk-health-check). Unknown action/job/argument -> refused, nothing called. Once per id (in memory; every action is safe to repeat). - internal/report/opactions.go: the executor; results re-sent until the hub stops listing the id. - scheduler.RunNow: refuses unknown / already-running jobs; OnDemand(ctx) makes an operator's offsite-integrity run even when not due. - ExtendAbandon never shortens the countdown and refuses in the hub phase; StopAbandon reports failure when the hub cancel failed (it said success). - Report ACK read cap 4 KiB -> 64 KiB (an ACK over the cap dropped every field in it). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -356,7 +356,21 @@ func (m *Manager) ExtendAbandon(days int) (time.Time, error) {
|
||||
}
|
||||
return time.Time{}, fmt.Errorf("no abandonment countdown is running on this box — nothing to extend")
|
||||
}
|
||||
// Decision 74: once the deletion is the HUB's, a box-side date changes the page and not the hub's
|
||||
// schedule — the hub would still delete on its own date. Stop it instead (StopAbandon cancels it
|
||||
// at the hub). Pinned by TestD1_ExtendRefusedWhileTheDeletionIsTheHubs.
|
||||
if st.HubPending {
|
||||
return time.Time{}, fmt.Errorf("the deletion is already pending at the hub (due %s) — it cannot be extended from the box; stop it instead",
|
||||
st.HubDueAt.Format("2006-01-02"))
|
||||
}
|
||||
due := m.abandonNow().UTC().AddDate(0, 0, days)
|
||||
// `09` §3 decision 185: an extension never moves the deletion EARLIER. „N days from now" can land
|
||||
// before today's due date (day 1 of 14, extend by 3); that would shorten the countdown, which no
|
||||
// lever may do. Pinned by TestD1_ExtendNeverShortensTheCountdown.
|
||||
if !due.After(st.DueAt) {
|
||||
return time.Time{}, fmt.Errorf("%d day(s) from now (%s) is not later than the current deletion date %s — that would shorten the countdown",
|
||||
days, due.Format("2006-01-02"), st.DueAt.Format("2006-01-02"))
|
||||
}
|
||||
if err := m.settings.UpdateOffboxStatus(func(o *settings.OffboxTarget) {
|
||||
o.AbandonAt = due.Format(time.RFC3339)
|
||||
}); err != nil {
|
||||
@@ -380,5 +394,13 @@ func (m *Manager) StopAbandon() error {
|
||||
return fmt.Errorf("no abandonment countdown is running on this box — nothing to stop")
|
||||
}
|
||||
m.CancelAbandon("stopped by an operator")
|
||||
// CancelAbandon keeps the countdown when the hub's pending deletion could not be cancelled (so the
|
||||
// sweep retries). Report that as a failure — an operator told „stopped" while the hub still deletes
|
||||
// on schedule is the comfort this project keeps removing. Pinned by
|
||||
// TestD1_StopReportsFailureWhenTheHubCancelFails.
|
||||
if after := m.AbandonStatus(); after.Active {
|
||||
return fmt.Errorf("the countdown could not be stopped (the hub's pending deletion was not cancelled; see the log) — it is still due %s",
|
||||
after.DueAt.Format("2006-01-02"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user