carlos / platform Public

console: open-uncertain ranks with landed, so an operator's abort at offline-landed reconciles it to reverting

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev dc790bf3f4a2e89678d6f551bea785115407fda0 parent c982249
2 files changed, +21 −2
  • internal/console/selfserve_job.go +4 −2
  • internal/e2e/selfserve/job_reconcile_test.go +17 −0
diff --git a/internal/console/selfserve_job.go b/internal/console/selfserve_job.go
index dd6498722..03eaaf7c6 100644
--- a/internal/console/selfserve_job.go
+++ b/internal/console/selfserve_job.go
@@ -149,11 +149,13 @@ var selfServeSets = map[string]struct {
// never moves a row to a lower rank. reverting ranks with landed, the last
// phase it can be entered from, so a reverting row may still be moved
// forward to the post-open phases by a record an operator opened, and
-// never back into the pre-copy.
+// never back into the pre-copy. open-uncertain ranks with them too: its
+// record is still offline-landed, so an operator's abort there moves the
+// row to reverting, and a committed open moves it to opened.
var selfServeRank = map[string]int{
ssRequested: 0, ssReserving: 1, ssQueued: 2, ssReports: 3, ssStaging: 4, ssPrechecks: 5, ssReady: 6,
ssRestage: 7, ssBarrier: 8, ssStopping: 9, ssSealing: 10, ssLanding: 11, ssLanded: 12, ssReverting: 12,
- ssOpenUncertain: 13, ssOpened: 14, ssHealth: 15, ssFinishing: 16, ssDone: 17,
+ ssOpenUncertain: 12, ssOpened: 14, ssHealth: 15, ssFinishing: 16, ssDone: 17,
}
func containsPhase(phases []string, p string) bool {
diff --git a/internal/e2e/selfserve/job_reconcile_test.go b/internal/e2e/selfserve/job_reconcile_test.go
index 1eee16e66..16398c105 100644
--- a/internal/e2e/selfserve/job_reconcile_test.go
+++ b/internal/e2e/selfserve/job_reconcile_test.go
@@ -261,6 +261,23 @@ WHERE id = ?`, time.Now().UnixNano(), rec.Incarnation, rec.RecordSeq, time.Now()
t.Fatalf("the row went back: %s", describe(r))
}
})
+ t.Run("an open-uncertain row an operator aborted goes to reverting", func(t *testing.T) {
+ // open-uncertain ranks with landed (and reverting): an operator's
+ // abort at offline-landed moves the row to reverting, never leaves
+ // it waiting on an open that can no longer happen.
+ w := newJobWorld(t)
+ row := w.admit()
+ w.phase(row.ID, "ready", 60)
+ w.down()
+ w.operatorTo(row.ID, provision.OfflineLanded)
+ w.consoleUntil(3, "landed", func() bool { return w.row(row.ID).Phase == "landed" })
+ w.setPhase(row.ID, "open-uncertain", "")
+ w.operatorTo(row.ID, provision.OfflineReverting)
+ w.consoleUntil(3, "reverting", func() bool { return w.row(row.ID).Phase == "reverting" })
+ if r := w.row(row.ID); r.PhaseStep != "finish" || r.Outcome != "" {
+ t.Fatalf("reconciled to %s", describe(r))
+ }
+ })
t.Run("the record is gone", func(t *testing.T) {
w := newJobWorld(t)
row := w.admit()