DLV-O4: manifest-accepted and manifest-refused carry the verdicts state's revision of the verdict they say (ADR 0622 §2)
The grants part follows verdicts by these events after its first view, so each must carry the revision it is at. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -152,7 +152,7 @@ func (ix *Indexer) judgeOver(ctx context.Context, fresh map[string]bool, over ma
|
||||
accepted = append(accepted, m)
|
||||
}
|
||||
}
|
||||
wrote, err := ix.writeVerdict(ctx, digests[name], v)
|
||||
wrote, revision, err := ix.writeVerdict(ctx, digests[name], v)
|
||||
if errors.Is(err, process.ErrNotYet) {
|
||||
return out, fmt.Errorf("the state %s is not on the bus yet: %w", VerdictsBucket, err)
|
||||
}
|
||||
@@ -171,12 +171,16 @@ func (ix *Indexer) judgeOver(ctx context.Context, fresh map[string]bool, over ma
|
||||
if v.Refused() {
|
||||
ix.logf("judge: %s", v.Why())
|
||||
if ix.SayRefused != nil {
|
||||
ix.SayRefused(ctx, delivery.RefusedOf(digests[name], v))
|
||||
r := delivery.RefusedOf(digests[name], v)
|
||||
r.Revision = revision
|
||||
ix.SayRefused(ctx, r)
|
||||
}
|
||||
} else if ix.SayAccepted != nil {
|
||||
// A manifest asking for bus state, newly accepted, is said whole to the bus module (issue 1966 D3, ADR 0595 §4).
|
||||
if m, problems := judge.Manifest(raws[name], predefined); len(problems) == 0 && len(m.BusState) > 0 {
|
||||
ix.SayAccepted(ctx, delivery.AcceptedOf(digests[name], v, m))
|
||||
a := delivery.AcceptedOf(digests[name], v, m)
|
||||
a.Revision = revision
|
||||
ix.SayAccepted(ctx, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,11 +307,13 @@ func (ix *Indexer) acceptedBefore(ctx context.Context, digest string, fresh map[
|
||||
}
|
||||
|
||||
// writeVerdict writes v under the digest's key unless the verdict held there says the same (ManifestVerdict.Same); wrote
|
||||
// says it was written.
|
||||
func (ix *Indexer) writeVerdict(ctx context.Context, digest string, v delivery.ManifestVerdict) (wrote bool, err error) {
|
||||
// says it was written, and revision is the verdicts state's revision of that write, which the event saying it carries
|
||||
// (novox/hq ADR 0622 §2). It is read back after the write: when another write came between, the revision read holds
|
||||
// another verdict and revision is 0, so a reader takes the later write's own event and never pairs v with its revision.
|
||||
func (ix *Indexer) writeVerdict(ctx context.Context, digest string, v delivery.ManifestVerdict) (wrote bool, revision uint64, err error) {
|
||||
key, err := delivery.VerdictsKey(digest)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, 0, err
|
||||
}
|
||||
err = write(ctx, ix.Verdicts, key, func(value []byte, found bool) ([]byte, bool, error) {
|
||||
wrote = false
|
||||
@@ -320,7 +326,15 @@ func (ix *Indexer) writeVerdict(ctx context.Context, digest string, v delivery.M
|
||||
next, err := delivery.EncodeManifestVerdict(v)
|
||||
return next, false, err
|
||||
})
|
||||
return wrote, err
|
||||
if err != nil || !wrote {
|
||||
return wrote, 0, err
|
||||
}
|
||||
if value, rev, found, err := ix.Verdicts.Get(ctx, key); err == nil && found {
|
||||
if cur, err := delivery.DecodeManifestVerdict(value); err == nil && cur.Same(v) {
|
||||
revision = rev
|
||||
}
|
||||
}
|
||||
return wrote, revision, nil
|
||||
}
|
||||
|
||||
// learnOwnBuild asks where the indexer's program is told which build it runs (OwnBuild: the node-engine's seat, never the
|
||||
|
||||
@@ -72,8 +72,10 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if m := module("good"); m.Verdict != "" {
|
||||
t.Fatalf("modules.good carries %q", m.Verdict)
|
||||
}
|
||||
if len(said) != 1 || said[0].Module != "bad" || said[0].Digest != bad || said[0].Judge != "judge-1" {
|
||||
t.Fatalf("said %+v", said)
|
||||
// ADR 0622 §2: the event carries the verdicts state's revision of the verdict it says.
|
||||
if _, rev, _, _ := ix.Verdicts.Get(ctx, bad); len(said) != 1 || said[0].Module != "bad" || said[0].Digest != bad ||
|
||||
said[0].Judge != "judge-1" || said[0].Revision == 0 || said[0].Revision != rev {
|
||||
t.Fatalf("said %+v (the verdict's revision %d)", said, rev)
|
||||
}
|
||||
// A new judge that judges alike writes nothing and says nothing again.
|
||||
ix.JudgeID = "judge-2"
|
||||
@@ -154,6 +156,9 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if needs := module("good").Needs; !slices.Contains(needs, "word:module") || len(catalogue.MissingManifestReads(needs, nil)) != 0 {
|
||||
t.Fatalf("modules.good needs %v", needs)
|
||||
}
|
||||
if _, rev, _, _ := ix.Verdicts.Get(ctx, moved); len(accepted) != 1 || accepted[0].Revision == 0 || accepted[0].Revision != rev {
|
||||
t.Fatalf("said accepted %+v, want the verdict's revision %d (ADR 0622 §2)", accepted, rev)
|
||||
}
|
||||
if len(accepted) != 1 || accepted[0].Module != "moved" || accepted[0].Digest != moved || accepted[0].Judge != "judge-2" ||
|
||||
len(accepted[0].BusState) != 2 || accepted[0].BusState[0].Name != "cache" || accepted[0].BusState[1].Template != "log" ||
|
||||
string(accepted[0].BusState[0].Options["history"]) != "8" {
|
||||
@@ -328,7 +333,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := ix.writeVerdict(ctx, digest, delivery.ManifestVerdict{Module: module, State: delivery.VerdictRefused,
|
||||
if _, _, err := ix.writeVerdict(ctx, digest, delivery.ManifestVerdict{Module: module, State: delivery.VerdictRefused,
|
||||
Problems: []string{module + " says tool-runner, which this judge does not know"}, Judge: "judge-0", At: time.Now()}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -336,7 +341,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
atStart := stale("tools", `{"module":"tools","version":"7"}`)
|
||||
ownRefusal := stale("client", `{"module":"client","version":"7"}`)
|
||||
if _, err := ix.writeVerdict(ctx, ownRefusal, delivery.ManifestVerdict{Module: "client", State: delivery.VerdictRefused,
|
||||
if _, _, err := ix.writeVerdict(ctx, ownRefusal, delivery.ManifestVerdict{Module: "client", State: delivery.VerdictRefused,
|
||||
Problems: []string{"x"}, Judge: ix.judgeID(), At: time.Now()}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user