carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package moves
2
3import (
4 "time"
5
6 "github.com/carlosframework/platform/internal/provision"
7)
8
9// AbortAfter is how long a Phase 1 move may stay preparing before it aborts
10// itself (spec §7.11: "a move whose readiness never comes aborts itself
11// after a bound, so an unreachable target never needs a human"; Plan 5
12// ruling K18). §13 pages an operator at 60 minutes with no promotable round;
13// the abort comes at six hours. The console's sweep (Plan 5 Task 7) CASes
14// provision.MoveGuardedAbort when AbortDue says so; nothing here writes.
15const AbortAfter = 6 * time.Hour
16
17// AbortDue reports whether rec's move is due its automatic abort at now: a
18// Phase 1 move (not legacy) still preparing, AbortAfter or more after the
19// later of its RequestedAt and its ReadyAt.
20//
21// The bound is measured from max(RequestedAt, ReadyAt) (ruling K18), not
22// from Move.UpdatedAt, which every record write stamps and so says nothing
23// about readiness. Today a preparing move has no ReadyAt (nothing demotes a
24// ready move to preparing), so the bound runs from the request; taking the
25// later of the two keeps it right should a demotion ever stamp one. A ready
26// move is not due: readiness came, and the cut is the operator's (or the
27// automatic cut's). A move with no request time is never due: there is no
28// evidence to measure from.
29func AbortDue(rec provision.Record, now time.Time) bool {
30 m := rec.Move
31 if m == nil || m.Legacy() || m.State != provision.MovePreparing || m.RequestedAt.IsZero() {
32 return false
33 }
34 return !now.Before(PreparingSince(m).Add(AbortAfter))
35}
36
37// PreparingSince is where a preparing move's clocks run from: the later of
38// its RequestedAt and its ReadyAt (ruling K18). The six-hour abort (AbortDue)
39// and the console's 60-minute page (§13) both measure from it, so the two
40// can never disagree about how long a move has prepared (Plan 6 preflight
41// L29).
42func PreparingSince(m *provision.MoveState) time.Time {
43 from := m.RequestedAt
44 if m.ReadyAt != nil && m.ReadyAt.After(from) {
45 from = *m.ReadyAt
46 }
47 return from
48}
49