D6i: a merge taken in before the verdicts state binds has each manifest judged as new and said at the bind, in the indexer's whole-module test (issue 1966 note 154, ADR 0668 §4)
Without the unjudged state the bind's pass accepted the refused manifest with a warning and the waiting one, and said manifest-accepted for both; the row settles Q3: the indexer says what grants follows, so the grants part is unchanged (no D8). Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -662,8 +662,9 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15
|
||||
js, ctx, _, modules := startIndexer(t, func(ctx context.Context, builds buildLog) {
|
||||
builds.end(t, "novox/mesh-catalog", "avahi", "modules/avahi")
|
||||
}, func(ctx context.Context, js jetstream.JetStream) {
|
||||
// The verdicts state and the stream of the indexer's events, as the controller makes them from its manifest.
|
||||
if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.VerdictsBucket, History: index.VerdictsHistory}); err != nil {
|
||||
// The indexer's state unjudged, as the controller makes it from its manifest; the verdicts state is made only once
|
||||
// the merge is taken in (issue 1966 note 154: a take-in at the start, before the verdicts state's bind).
|
||||
if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.UnjudgedBucket, History: 1}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
@@ -707,7 +708,20 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15
|
||||
t.Errorf("manifest = %+v err %v, want avahi and the file's bytes", got, err)
|
||||
}
|
||||
|
||||
verdicts, err := js.KeyValue(ctx, index.VerdictsBucket)
|
||||
// 1966 (ADR 0668 §4, note 154): the take-in wrote its four manifests with no verdicts state on the bus, so it keeps
|
||||
// them in its state unjudged; when the verdicts state binds, each is judged as new (bad refused in full, never as a
|
||||
// warning), every accepted one is said as manifest-accepted, and the state is left empty.
|
||||
unjudged, err := js.KeyValue(ctx, index.UnjudgedBucket)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kept, _ := unjudged.Keys(ctx)
|
||||
for _, raw := range []string{string(manifest), judged["good"], judged["bad"], judged["later"]} {
|
||||
if !slices.Contains(kept, meshcatalogclient.ManifestDigest([]byte(raw))) {
|
||||
t.Errorf("the take-in's new manifest %s is not kept unjudged: the state holds %v", meshcatalogclient.ManifestDigest([]byte(raw)), kept)
|
||||
}
|
||||
}
|
||||
verdicts, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.VerdictsBucket, History: index.VerdictsHistory})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -732,12 +746,20 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15
|
||||
if !strings.Contains(strings.Join(got["bad"].Problems, " "), `provides "amqp"`) || strings.Join(got["later"].Unknown, " ") != "a-field-from-later" {
|
||||
t.Errorf("the refusal names no problem or the wait no field: %+v", got)
|
||||
}
|
||||
// The pass ends the state's keys after it wrote and said every verdict.
|
||||
left, _ := unjudged.Keys(ctx)
|
||||
for deadline := time.Now().Add(10 * time.Second); len(left) != 0 && time.Now().Before(deadline); time.Sleep(50 * time.Millisecond) {
|
||||
left, _ = unjudged.Keys(ctx)
|
||||
}
|
||||
if len(left) != 0 {
|
||||
t.Errorf("the state unjudged still holds %v within 10 s, once every manifest has its verdict", left)
|
||||
}
|
||||
// manifest-refused, said once for each refusal (a wait is no refusal).
|
||||
events, err := js.Stream(ctx, "EVENTS")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
said := map[string]bool{}
|
||||
said, acceptedSaid := map[string]bool{}, map[string]bool{}
|
||||
for seq := uint64(1); ; seq++ {
|
||||
msg, err := events.GetMsg(ctx, seq)
|
||||
if err != nil {
|
||||
@@ -747,10 +769,17 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15
|
||||
if msg.Subject == "mesh.seat.mesh-catalog.event."+meshcatalog.EventManifestRefused && json.Unmarshal(msg.Data, &r) == nil {
|
||||
said[r.Module] = true
|
||||
}
|
||||
var a meshcatalog.ManifestAcceptedEvent
|
||||
if msg.Subject == "mesh.seat.mesh-catalog.event."+meshcatalog.EventManifestAccepted && json.Unmarshal(msg.Data, &a) == nil {
|
||||
acceptedSaid[a.Module] = true
|
||||
}
|
||||
}
|
||||
if !said["bad"] || said["later"] || said["good"] {
|
||||
t.Errorf("manifest-refused said for %v, want bad only", said)
|
||||
}
|
||||
if !acceptedSaid["good"] || acceptedSaid["bad"] || acceptedSaid["later"] {
|
||||
t.Errorf("manifest-accepted said for %v, want good and no refused or waiting one", acceptedSaid)
|
||||
}
|
||||
// How a composer holds a refused module by these verdicts is the node-engine's to test (ADR 0593 §7: the composer
|
||||
// and its bus reader are its own).
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user