From 3ed2a3dd331696bd09404e6d8ee33889a5ee124e Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 10 Nov 2026 23:45:46 +0100 Subject: [PATCH] The indexer says take-in.taken under every claimed entry's own key too (issue 1966, note 195) A merge waiting behind a gathered group is named by indexer_pending under its own key; when the group ends it joins the group's revision under the oldest member's key, so its own key was never said taken. takenWaits now also says every claimed entry's key, no key twice. T8 checks the merge behind the group ends under its own key. Builds: design 47 "Taken in by the indexer it names" (A wait is bounded, said and recoverable); 1966/AC195-1, AC195-3 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ --- .../mesh-delivery-indexer/internal/index/pending.go | 13 ++++++++----- .../internal/index/pending_test.go | 8 ++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/modules/mesh-delivery-indexer/internal/index/pending.go b/modules/mesh-delivery-indexer/internal/index/pending.go index 038a9275..0f6515c6 100644 --- a/modules/mesh-delivery-indexer/internal/index/pending.go +++ b/modules/mesh-delivery-indexer/internal/index/pending.go @@ -1093,11 +1093,11 @@ func (ix *Indexer) takeInWholeBy(ctx context.Context, entries []PendingEntry, ow return applied, nil } -// takenWaits are the taken events of a take-in: every wait the entries were said under (saidWaits) and every wait -// indexer_pending names the entries by (PendingWaits: a revision by its oldest merge's key, a group by its g. key) not -// already ended by one of those, so a wait the watchman learned of without the indexer marking it (seeded from -// indexer_pending, or said by the own-build-unknown path) ends too (design 47, Taken in by the indexer it names). No key is -// said twice. +// takenWaits are the taken events of a take-in: every wait the entries were said under (saidWaits), every wait +// indexer_pending names the claimed entries by now (WaitsOf: a revision by its oldest merge's key, a group by its g. key) and +// the key of every claimed entry, since indexer_pending named it by that key earlier when it waited behind a group. So a wait +// the watchman learned of without the indexer marking it (seeded from indexer_pending, or said by the own-build-unknown +// path) ends too (design 47, Taken in by the indexer it names). No key is said twice. func takenWaits(entries []PendingEntry) []takein.TakeIn { out := saidWaits(entries) said := map[string]bool{} @@ -1115,6 +1115,9 @@ func takenWaits(entries []PendingEntry) []takein.TakeIn { for _, g := range slices.Sorted(maps.Keys(w.Behind)) { named = append(named, revisionWait(takein.TakeInTaken, w.Behind[g], w.Behind[g][len(w.Behind[g])-1].Value.WaitsFor)) } + for _, e := range entries { + named = append(named, revisionWait(takein.TakeInTaken, []PendingEntry{e}, e.Value.WaitsFor)) + } for _, t := range named { if !said[t.Key] { said[t.Key] = true diff --git a/modules/mesh-delivery-indexer/internal/index/pending_test.go b/modules/mesh-delivery-indexer/internal/index/pending_test.go index 3043d1b1..27bff288 100644 --- a/modules/mesh-delivery-indexer/internal/index/pending_test.go +++ b/modules/mesh-delivery-indexer/internal/index/pending_test.go @@ -228,8 +228,8 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633) b.arrive(t, 9, b.merge(32, sha('d'), "tree-avahi-4", "tree-indexer-2")) b.said = nil b.arrive(t, 10, b.merge(33, sha('e'), "tree-avahi-5", b.base.Trees["modules/"+Module])) - if want := []string{"taken " + takein.PendingKey(8)}; !slices.Equal(b.events(), want) || len(b.keys()) != 0 { - t.Errorf("said %v, pending %v: want %v once", b.events(), b.keys(), want) + if want := []string{"taken " + takein.PendingKey(8), "taken " + takein.PendingKey(9), "taken " + takein.PendingKey(10)}; !slices.Equal(b.events(), want) || len(b.keys()) != 0 { + t.Errorf("said %v, pending %v: want %v, the wait's key (m.8, said pending) once and each other entry's own", b.events(), b.keys(), want) } }) t.Run("T7 and T3 a merge alone, an indexer change, a merge behind it and a revert", func(t *testing.T) { @@ -287,7 +287,7 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633) if len(b.keys()) != 0 || b.fp(t, Module) != own || b.commit(t, "avahi") != sha('e') { t.Fatalf("revert: pending %v, indexer %s, avahi at %s: want all taken in", b.keys(), b.fp(t, Module), b.commit(t, "avahi")) } - if want := []string{"pending " + takein.PendingKey(2), "taken " + takein.PendingKey(2)}; !slices.Equal(b.events(), want) { + if want := []string{"pending " + takein.PendingKey(2), "taken " + takein.PendingKey(2), "taken " + takein.PendingKey(3), "taken " + takein.PendingKey(4)}; !slices.Equal(b.events(), want) { t.Errorf("said %v, want %v", b.events(), want) } }) @@ -487,7 +487,7 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633) if len(b.keys()) != 0 || b.commit(t, "avahi") != sha('6') { t.Fatalf("end: pending %v, avahi at %s: want the group and the merge behind it taken in", b.keys(), b.commit(t, "avahi")) } - if want := []string{"pending g.feat/take-in", "taken " + takein.PendingKey(2), "pending g.feat/take-in", "taken g.feat/take-in", "taken " + takein.PendingKey(1)}; !slices.Equal(b.events(), want) { + if want := []string{"pending g.feat/take-in", "taken " + takein.PendingKey(2), "pending g.feat/take-in", "taken g.feat/take-in", "taken " + takein.PendingKey(1), "taken " + takein.PendingKey(3), "taken " + takein.PendingKey(4)}; !slices.Equal(b.events(), want) { t.Errorf("said %v, want %v", b.events(), want) } // R1: the end published again after the take-in changes nothing and is not delivered again.