delivery: indexer_pending's answer, so the view names a module waiting for its indexer (ADR 0633 §5, issue 1585)
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
@@ -250,6 +250,17 @@ func TestSourceValuesRoundTrip(t *testing.T) { // 1200/AC3
|
||||
t.Errorf("take-in %s round trip: %+v %v", ti.Key, got, err)
|
||||
}
|
||||
}
|
||||
// 1585/T12: indexer_pending's answer reads back; a wait of neither kind is refused.
|
||||
pa := PendingAnswer{Waits: []PendingWait{{Key: PendingKey(12), What: TakeInRevision, Merges: sampleTakeIns(since)[0].Merges,
|
||||
WaitsFor: "src2:abc", Since: since, Holds: []string{"mesh-delivery-indexer"}, Said: "take-in.pending." + PendingKey(12), SaidAt: since}}}
|
||||
if data, err := json.Marshal(pa); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if got, err := DecodePendingAnswer(data); err != nil || !reflect.DeepEqual(got, pa) {
|
||||
t.Errorf("pending answer round trip: %+v %v", got, err)
|
||||
}
|
||||
if _, err := DecodePendingAnswer([]byte(`{"waits":[{"key":"m.1","what":"held"}]}`)); err == nil {
|
||||
t.Error("a pending answer with a wait of neither kind accepted")
|
||||
}
|
||||
// 1280: the taken and reach values (ADR 0556).
|
||||
tk := Taken{Repository: "novox/mesh-sdk", Merge: "cccc", At: time.Date(2026, 10, 26, 20, 0, 0, 0, time.UTC)}
|
||||
data, err = EncodeTaken(tk)
|
||||
|
||||
@@ -166,3 +166,44 @@ func DecodeTakeIn(data []byte) (TakeIn, error) {
|
||||
|
||||
// SameTakeIn says whether two take-in bodies are the same value.
|
||||
func SameTakeIn(a, b TakeIn) bool { return reflect.DeepEqual(a, b) }
|
||||
|
||||
// PendingWait is one wait the indexer's tool indexer_pending answers (novox/hq ADR 0633 §5), as the view reads it to
|
||||
// name a module waiting for its revision's indexer. Key and What are a take-in event's: a revision under its oldest
|
||||
// merge's key, waiting for the indexer build WaitsFor (empty while it is worked out), or a group being gathered under
|
||||
// its group key, with Members every approved member and Merges those held so far. A revision that waits behind a
|
||||
// group being gathered names that group's key in Behind. Holds are the modules it holds back: every module of its
|
||||
// merges' trees. Said is the last take-in event said of it (`take-in.<kind>.<key>`) and SaidAt when.
|
||||
type PendingWait struct {
|
||||
Key string `json:"key"`
|
||||
What string `json:"what"`
|
||||
Merges []GroupMerge `json:"merges"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Members []Head `json:"members,omitempty"`
|
||||
Behind string `json:"behind,omitempty"`
|
||||
WaitsFor string `json:"waits-for,omitempty"`
|
||||
Since time.Time `json:"since"`
|
||||
Holds []string `json:"holds"`
|
||||
Said string `json:"said,omitempty"`
|
||||
SaidAt time.Time `json:"said-at,omitzero"`
|
||||
}
|
||||
|
||||
// PendingAnswer is indexer_pending's answer: every wait, oldest first, and the pending keys that do not read.
|
||||
type PendingAnswer struct {
|
||||
Waits []PendingWait `json:"waits"`
|
||||
Unread []string `json:"unread,omitempty"`
|
||||
}
|
||||
|
||||
// DecodePendingAnswer reads indexer_pending's answer, refusing a wait that is not a revision or a group, or names no
|
||||
// key.
|
||||
func DecodePendingAnswer(data []byte) (PendingAnswer, error) {
|
||||
var a PendingAnswer
|
||||
if err := json.Unmarshal(data, &a); err != nil {
|
||||
return a, fmt.Errorf("delivery: not an answer of indexer_pending: %w", err)
|
||||
}
|
||||
for _, w := range a.Waits {
|
||||
if w.Key == "" || (w.What != TakeInRevision && w.What != TakeInGroup) {
|
||||
return a, fmt.Errorf("delivery: indexer_pending answers a wait %q of %q, not a revision or a group", w.Key, w.What)
|
||||
}
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user