D1: the build step part gains the state again, run, again-at, passing and the verb drop; the three build seats regenerated (ADR 0664 §1, §4, issue 1748)
Shared lines for the join with milestone G: contracts/parts/build-step.json, the three seats' fixtures and generated contract files. Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -18,6 +18,7 @@ const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,7 +29,7 @@ const (
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
@@ -117,6 +118,41 @@ func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByDroppedIDKey is the key of one value of the state pauses under the form "dropped.<id>".
|
||||
func PausesByDroppedIDKey(id string) string { return "dropped." + id }
|
||||
|
||||
// ParsePausesByDroppedIDKey reads the parts of a key of the form "dropped.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByDroppedIDKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "dropped.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[8:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByDroppedIDValue reads one value of the state pauses under the form "dropped.<id>", refusing a field PausesByDroppedIDValue does not know and any text after the value.
|
||||
func DecodePausesByDroppedIDValue(raw []byte) (PausesByDroppedIDValue, error) {
|
||||
var v PausesByDroppedIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
@@ -245,6 +281,16 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// FetchBesideItem is a type of the contract.
|
||||
type FetchBesideItem struct {
|
||||
Commit string `json:"commit"`
|
||||
@@ -433,19 +479,25 @@ type RunProgram struct {
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when the bus gives the ask again, for the state again (RFC 3339 time)
|
||||
AgainAt *time.Time `json:"again-at,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so
|
||||
Passing bool `json:"passing,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt *time.Time `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Result *StepResult `json:"result,omitempty"`
|
||||
// which run of the ask this is, counted by the bus's delivery count (1 for the first)
|
||||
Run int64 `json:"run,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started time.Time `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
// running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
@@ -588,6 +640,19 @@ type ResumeInput struct {
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DropInput is what drop takes.
|
||||
type DropInput struct {
|
||||
// who drops it
|
||||
By string `json:"by,omitempty"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// why the caller no longer waits
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
@@ -603,6 +668,9 @@ type StepsByNodeIDValue = Step
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByDroppedIDValue is one value of the state pauses under the key dropped.<id>.
|
||||
type PausesByDroppedIDValue = Drop
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
|
||||
@@ -53,6 +53,12 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v CheckAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.check$")},
|
||||
{name: "a finished run step whose program exited non-zero", subject: "", given: "{\"ended\":\"2026-11-05T10:01:00Z\",\"id\":\"r5e6\",\"node\":\"ace\",\"result\":{\"built\":true,\"exit\":2,\"key\":\"program-0123456789abcdef\",\"said\":\"the facts name no head\"},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"failed\",\"tool\":\"check\",\"v\":1}", wire: "{\"ended\":\"2026-11-05T10:01:00Z\",\"id\":\"r5e6\",\"node\":\"ace\",\"result\":{\"built\":true,\"exit\":2,\"key\":\"program-0123456789abcdef\",\"said\":\"the facts name no head\"},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"failed\",\"tool\":\"check\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a step ended on a transport fault, given again by the bus", subject: "", given: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}", wire: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,7 +29,7 @@ const (
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
@@ -117,6 +118,41 @@ func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByDroppedIDKey is the key of one value of the state pauses under the form "dropped.<id>".
|
||||
func PausesByDroppedIDKey(id string) string { return "dropped." + id }
|
||||
|
||||
// ParsePausesByDroppedIDKey reads the parts of a key of the form "dropped.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByDroppedIDKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "dropped.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[8:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByDroppedIDValue reads one value of the state pauses under the form "dropped.<id>", refusing a field PausesByDroppedIDValue does not know and any text after the value.
|
||||
func DecodePausesByDroppedIDValue(raw []byte) (PausesByDroppedIDValue, error) {
|
||||
var v PausesByDroppedIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
@@ -245,6 +281,16 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// FetchBesideItem is a type of the contract.
|
||||
type FetchBesideItem struct {
|
||||
Commit string `json:"commit"`
|
||||
@@ -433,19 +479,25 @@ type RunProgram struct {
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when the bus gives the ask again, for the state again (RFC 3339 time)
|
||||
AgainAt *time.Time `json:"again-at,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so
|
||||
Passing bool `json:"passing,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt *time.Time `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Result *StepResult `json:"result,omitempty"`
|
||||
// which run of the ask this is, counted by the bus's delivery count (1 for the first)
|
||||
Run int64 `json:"run,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started time.Time `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
// running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
@@ -588,6 +640,19 @@ type ResumeInput struct {
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DropInput is what drop takes.
|
||||
type DropInput struct {
|
||||
// who drops it
|
||||
By string `json:"by,omitempty"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// why the caller no longer waits
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
@@ -603,6 +668,9 @@ type StepsByNodeIDValue = Step
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByDroppedIDValue is one value of the state pauses under the key dropped.<id>.
|
||||
type PausesByDroppedIDValue = Drop
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ func TestFixtures(t *testing.T) {
|
||||
}, subjectIs: nil},
|
||||
{name: "a build ask", subject: "mesh.seat.node-build-image.accept.delivery", given: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}", wire: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}",
|
||||
decode: func(b []byte) (any, error) { var v DeliveryAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.delivery$")},
|
||||
{name: "a step ended on a transport fault, given again by the bus", subject: "", given: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}", wire: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,7 +29,7 @@ const (
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
@@ -117,6 +118,41 @@ func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByDroppedIDKey is the key of one value of the state pauses under the form "dropped.<id>".
|
||||
func PausesByDroppedIDKey(id string) string { return "dropped." + id }
|
||||
|
||||
// ParsePausesByDroppedIDKey reads the parts of a key of the form "dropped.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByDroppedIDKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "dropped.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[8:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByDroppedIDValue reads one value of the state pauses under the form "dropped.<id>", refusing a field PausesByDroppedIDValue does not know and any text after the value.
|
||||
func DecodePausesByDroppedIDValue(raw []byte) (PausesByDroppedIDValue, error) {
|
||||
var v PausesByDroppedIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
@@ -245,6 +281,16 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// FetchBesideItem is a type of the contract.
|
||||
type FetchBesideItem struct {
|
||||
Commit string `json:"commit"`
|
||||
@@ -433,19 +479,25 @@ type RunProgram struct {
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when the bus gives the ask again, for the state again (RFC 3339 time)
|
||||
AgainAt *time.Time `json:"again-at,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so
|
||||
Passing bool `json:"passing,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt *time.Time `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Result *StepResult `json:"result,omitempty"`
|
||||
// which run of the ask this is, counted by the bus's delivery count (1 for the first)
|
||||
Run int64 `json:"run,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started time.Time `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
// running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
@@ -588,6 +640,19 @@ type ResumeInput struct {
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DropInput is what drop takes.
|
||||
type DropInput struct {
|
||||
// who drops it
|
||||
By string `json:"by,omitempty"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// why the caller no longer waits
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
@@ -603,6 +668,9 @@ type StepsByNodeIDValue = Step
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByDroppedIDValue is one value of the state pauses under the key dropped.<id>.
|
||||
type PausesByDroppedIDValue = Drop
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v CheckAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.check$")},
|
||||
{name: "a finished check step of a TypeScript merge preview", subject: "", given: "{\"ended\":\"2026-11-05T10:01:00Z\",\"id\":\"c3d6\",\"node\":\"ace\",\"result\":{\"fetch\":{\"base\":\"abcdef0123456789abcdef0123456789abcdef01\",\"changed\":[\"modules/m/package.json\"],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"merge\":\"0123456789abcdef0123456789abcdef01234567\",\"modules\":[\"modules/m\"],\"trees\":{\"modules/m\":{\"manifest\":\"0581b699d9d05517e69b21f5cedbeb2eee8aba2b205280b561be731594d7feef\",\"tree\":\"0123456789abcdef0123456789abcdef01234567\"}},\"workspace\":\"mvii1sxt979f67\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"check\",\"v\":1}", wire: "{\"ended\":\"2026-11-05T10:01:00Z\",\"id\":\"c3d6\",\"node\":\"ace\",\"result\":{\"fetch\":{\"base\":\"abcdef0123456789abcdef0123456789abcdef01\",\"changed\":[\"modules/m/package.json\"],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"merge\":\"0123456789abcdef0123456789abcdef01234567\",\"modules\":[\"modules/m\"],\"trees\":{\"modules/m\":{\"manifest\":\"0581b699d9d05517e69b21f5cedbeb2eee8aba2b205280b561be731594d7feef\",\"tree\":\"0123456789abcdef0123456789abcdef01234567\"}},\"workspace\":\"mvii1sxt979f67\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"check\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a step ended on a transport fault, given again by the bus", subject: "", given: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}", wire: "{\"again-at\":\"2026-11-05T10:01:30Z\",\"ended\":\"2026-11-05T10:00:30Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"passing\":true,\"reason\":\"fetching the commit: kex_exchange_identification: read: Connection reset by peer\",\"run\":1,\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"again\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -38,6 +38,36 @@
|
||||
"type": "object",
|
||||
"description": "whether the node is paused"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"description": "End an ask this node holds for a caller that no longer waits for it: a step not yet running is refused when it is pulled, one running is cancelled and ends refused, naming who dropped it and why. Writes dropped.<id> in the pauses state; the build module removes the key when it has acted.",
|
||||
"callers": "the build seats' asker (the builder and the checker)",
|
||||
"input": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "the ask's id"
|
||||
},
|
||||
"by": {
|
||||
"type": "string",
|
||||
"description": "who drops it"
|
||||
},
|
||||
"why": {
|
||||
"type": "string",
|
||||
"description": "why the caller no longer waits"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"why"
|
||||
]
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"description": "whether the ask was held here"
|
||||
}
|
||||
}
|
||||
],
|
||||
"defs": {
|
||||
@@ -404,7 +434,7 @@
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "running, passed, failed or refused"
|
||||
"description": "running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused"
|
||||
},
|
||||
"started": {
|
||||
"type": "string",
|
||||
@@ -435,6 +465,19 @@
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"run": {
|
||||
"type": "integer",
|
||||
"description": "which run of the ask this is, counted by the bus's delivery count (1 for the first)"
|
||||
},
|
||||
"again-at": {
|
||||
"type": "string",
|
||||
"description": "when the bus gives the ask again, for the state again (RFC 3339 time)",
|
||||
"format": "date-time"
|
||||
},
|
||||
"passing": {
|
||||
"type": "boolean",
|
||||
"description": "true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -476,6 +519,30 @@
|
||||
],
|
||||
"description": "the toolchain a node reports"
|
||||
},
|
||||
"Drop": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"by": {
|
||||
"type": "string"
|
||||
},
|
||||
"why": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)",
|
||||
"format": "date-time"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"why"
|
||||
],
|
||||
"description": "an ask a caller no longer waits for"
|
||||
},
|
||||
"Pause": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -312,5 +312,32 @@
|
||||
"said": "the facts name no head"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a step ended on a transport fault, given again by the bus",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "again",
|
||||
"started": "2026-11-05T10:00:00Z",
|
||||
"ended": "2026-11-05T10:00:30Z",
|
||||
"reason": "fetching the commit: kex_exchange_identification: read: Connection reset by peer",
|
||||
"run": 1,
|
||||
"again-at": "2026-11-05T10:01:30Z",
|
||||
"passing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "an ask dropped by the caller that no longer waits",
|
||||
"of": "state:pauses/dropped.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"name": "drop names the ask and why",
|
||||
"of": "verb:drop.input",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -58,6 +58,13 @@
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "dropped.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Drop"
|
||||
},
|
||||
"description": "an ask its caller no longer waits for"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
|
||||
@@ -59,5 +59,32 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a step ended on a transport fault, given again by the bus",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "again",
|
||||
"started": "2026-11-05T10:00:00Z",
|
||||
"ended": "2026-11-05T10:00:30Z",
|
||||
"reason": "fetching the commit: kex_exchange_identification: read: Connection reset by peer",
|
||||
"run": 1,
|
||||
"again-at": "2026-11-05T10:01:30Z",
|
||||
"passing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "an ask dropped by the caller that no longer waits",
|
||||
"of": "state:pauses/dropped.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"name": "drop names the ask and why",
|
||||
"of": "verb:drop.input",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -58,6 +58,13 @@
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "dropped.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Drop"
|
||||
},
|
||||
"description": "an ask its caller no longer waits for"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
|
||||
@@ -131,5 +131,32 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a step ended on a transport fault, given again by the bus",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "again",
|
||||
"started": "2026-11-05T10:00:00Z",
|
||||
"ended": "2026-11-05T10:00:30Z",
|
||||
"reason": "fetching the commit: kex_exchange_identification: read: Connection reset by peer",
|
||||
"run": 1,
|
||||
"again-at": "2026-11-05T10:01:30Z",
|
||||
"passing": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "an ask dropped by the caller that no longer waits",
|
||||
"of": "state:pauses/dropped.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"name": "drop names the ask and why",
|
||||
"of": "verb:drop.input",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"by": "mesh-delivery-builder",
|
||||
"why": "a newer fingerprint supersedes it"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -58,6 +58,13 @@
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "dropped.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Drop"
|
||||
},
|
||||
"description": "an ask its caller no longer waits for"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
@@ -66,6 +67,23 @@ export function parsePausesByPausedNodeKey(_key: string): { node: string } | und
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
@@ -110,6 +128,9 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
export type Fetch = buildStep.Fetch;
|
||||
export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
@@ -159,6 +180,9 @@ export type StepsByNodeIDValue = Step;
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key dropped.<id>. */
|
||||
export type PausesByDroppedIDValue = Drop;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
@@ -62,6 +63,16 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface FetchBesideItem {
|
||||
"commit": string;
|
||||
"repository": string;
|
||||
@@ -244,19 +255,25 @@ export interface RunProgram {
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when the bus gives the ask again, for the state again (RFC 3339 time) */
|
||||
"again-at"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
/** true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so */
|
||||
"passing"?: boolean;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
"result"?: StepResult;
|
||||
/** which run of the ask this is, counted by the bus's delivery count (1 for the first) */
|
||||
"run"?: number;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
/** running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
@@ -396,3 +413,16 @@ export interface ResumeInput {
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what drop takes. */
|
||||
export interface DropInput {
|
||||
/** who drops it */
|
||||
"by"?: string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** why the caller no longer waits */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
@@ -66,6 +67,23 @@ export function parsePausesByPausedNodeKey(_key: string): { node: string } | und
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
@@ -110,6 +128,9 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
export type Fetch = buildStep.Fetch;
|
||||
export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
@@ -159,6 +180,9 @@ export type StepsByNodeIDValue = Step;
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key dropped.<id>. */
|
||||
export type PausesByDroppedIDValue = Drop;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
@@ -62,6 +63,16 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface FetchBesideItem {
|
||||
"commit": string;
|
||||
"repository": string;
|
||||
@@ -244,19 +255,25 @@ export interface RunProgram {
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when the bus gives the ask again, for the state again (RFC 3339 time) */
|
||||
"again-at"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
/** true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so */
|
||||
"passing"?: boolean;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
"result"?: StepResult;
|
||||
/** which run of the ask this is, counted by the bus's delivery count (1 for the first) */
|
||||
"run"?: number;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
/** running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
@@ -396,3 +413,16 @@ export interface ResumeInput {
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what drop takes. */
|
||||
export interface DropInput {
|
||||
/** who drops it */
|
||||
"by"?: string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** why the caller no longer waits */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
@@ -66,6 +67,23 @@ export function parsePausesByPausedNodeKey(_key: string): { node: string } | und
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
@@ -110,6 +128,9 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
export type Fetch = buildStep.Fetch;
|
||||
export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
@@ -159,6 +180,9 @@ export type StepsByNodeIDValue = Step;
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key dropped.<id>. */
|
||||
export type PausesByDroppedIDValue = Drop;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
@@ -62,6 +63,16 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface FetchBesideItem {
|
||||
"commit": string;
|
||||
"repository": string;
|
||||
@@ -244,19 +255,25 @@ export interface RunProgram {
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when the bus gives the ask again, for the state again (RFC 3339 time) */
|
||||
"again-at"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
/** true when the step ended on a fault that passes (a transport fault), so a failed end after the last run says so */
|
||||
"passing"?: boolean;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
"result"?: StepResult;
|
||||
/** which run of the ask this is, counted by the bus's delivery count (1 for the first) */
|
||||
"run"?: number;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
/** running, again (ended on a transport fault, to be given again by the bus after again-at), passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
@@ -396,3 +413,16 @@ export interface ResumeInput {
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what drop takes. */
|
||||
export interface DropInput {
|
||||
/** who drops it */
|
||||
"by"?: string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** why the caller no longer waits */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user