The router holds what an open walk touches and tells its result once; it can do so only if plan-moved names the walk's start and end, the modules and machines it moves, what a moved tool runner or node-engine carries there, and how long to hold.
82 lines
2.9 KiB
Go
82 lines
2.9 KiB
Go
package inventory
|
|
|
|
import "time"
|
|
|
|
// A walk says when it starts and when it ends (novox/hq ADR 0308 decision 1): the save that starts it and the
|
|
// save that ends it are marked, so `plan-moved` names what the walk touches, its bound and its outcome on those
|
|
// two saves, and on no other. The marks are kept in the walk's times, so a controller replaced mid-walk (a core
|
|
// walk replaces it) neither says a start again nor misses the end.
|
|
|
|
// The moments of a walk `plan-moved` names.
|
|
const (
|
|
WalkStarted = "started"
|
|
WalkEnded = "ended"
|
|
)
|
|
|
|
// The outcomes of an ended walk (ADR 0308 decision 1).
|
|
const (
|
|
WalkDelivered = "delivered"
|
|
WalkFailed = "failed"
|
|
WalkStopped = "stopped"
|
|
)
|
|
|
|
// Live says the walk is walking: cut, not waiting for its delivery's word, and not ended.
|
|
func (p Plan) Live() bool { return p.Open() && !p.Batch() && !p.Waiting() }
|
|
|
|
// Ended says the walk is in a state it does not leave by itself: done, failed or superseded.
|
|
func (p Plan) Ended() bool {
|
|
return p.State == PlanDone || p.State == PlanFailed || p.State == PlanSuperseded
|
|
}
|
|
|
|
// Outcome is how an ended walk ended: delivered when done; stopped when a person or the delivery's owner stopped
|
|
// it, or a newer walk took it over; failed otherwise. Empty for a walk not ended.
|
|
func (p Plan) Outcome() string {
|
|
switch {
|
|
case p.State == PlanDone:
|
|
return WalkDelivered
|
|
case p.State == PlanSuperseded:
|
|
return WalkStopped
|
|
case p.State == PlanFailed && p.Delivery != nil && p.Delivery.Stopped != "":
|
|
return WalkStopped
|
|
case p.State == PlanFailed:
|
|
return WalkFailed
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// markWalk marks the save that starts or ends the walk, in its times and in WalkSaid, and returns what undoes
|
|
// the mark should the save not be written. A walk starts on the first save that finds it live — when it is cut
|
|
// and needs no word, or when it is let go — which is before its first tier is asked, and so before anything is
|
|
// sent: what it restarts is held from its first send on. It starts again when a failed walk is retried. It ends
|
|
// on the first save that finds it ended after it started; one that ends without ever starting (a batch that
|
|
// moved nothing, a walk stopped while it waited for its word) touched nothing and says neither. A walk kept
|
|
// before its times were (ADR 0282 decision 6) is not marked; a release plan is, its times holding only these.
|
|
func (p *Plan) markWalk(now time.Time) (undo func()) {
|
|
p.WalkSaid = ""
|
|
if p.Batch() || (p.Times == nil && p.Release == nil) {
|
|
return func() {}
|
|
}
|
|
var was *PlanTimes
|
|
if p.Times != nil {
|
|
kept := *p.Times
|
|
was = &kept
|
|
}
|
|
times := PlanTimes{}
|
|
if p.Times != nil {
|
|
times = *p.Times
|
|
}
|
|
at := now.UTC()
|
|
switch {
|
|
case p.Live() && (times.Started == nil || times.Ended != nil):
|
|
times.Started, times.Ended = &at, nil
|
|
p.WalkSaid = WalkStarted
|
|
case p.Ended() && times.Started != nil && times.Ended == nil:
|
|
times.Ended = &at
|
|
p.WalkSaid = WalkEnded
|
|
default:
|
|
return func() {}
|
|
}
|
|
p.Times = ×
|
|
return func() { p.Times, p.WalkSaid = was, "" }
|
|
}
|