Merge pull request 'Review parts are asked one at a time: the node judges one at a time (issue 1966, quick fix)' (#651) from fix/1966-kb-one-part into main

This commit was merged in pull request #651.
This commit is contained in:
2026-11-10 07:33:48 +00:00
2 changed files with 6 additions and 5 deletions
@@ -25,8 +25,9 @@ const HeadPart = "head"
// MostFrameBytes is the most the frame of a section part holds. // MostFrameBytes is the most the frame of a section part holds.
const MostFrameBytes = 16 << 10 const MostFrameBytes = 16 << 10
// MostParallelParts is how many judgements of one version run at once. // MostParallelParts is how many judgements of one version run at once. The node runs one judgement at a time (ADR 0278
const MostParallelParts = 2 // §25), so a second ask would only spend its own bound waiting for the first (issue 1966).
const MostParallelParts = 1
// PartReview is the latest verdict of one part: the digest of what it was judged with, so a part whose text and frame are // PartReview is the latest verdict of one part: the digest of what it was judged with, so a part whose text and frame are
// unchanged keeps it. // unchanged keeps it.
@@ -20,7 +20,7 @@ func TestAVersionIsReviewedInPartsAndARevisionJudgesOnlyWhatChanged(t *testing.T
var asked []string var asked []string
var failOn string var failOn string
inner := w.k.Judge inner := w.k.Judge
// The first two judgements wait for each other, so the test sees them run at once and not one after the other. // The first judgement is counted at once; the test sees that no second one runs beside it.
var arrived atomic.Int32 var arrived atomic.Int32
meet := make(chan struct{}) meet := make(chan struct{})
w.k.Judge = func(q string, s map[string]any, model string) (json.RawMessage, string, error) { w.k.Judge = func(q string, s map[string]any, model string) (json.RawMessage, string, error) {
@@ -63,8 +63,8 @@ func TestAVersionIsReviewedInPartsAndARevisionJudgesOnlyWhatChanged(t *testing.T
if e.Current.Status != StatusProposed || e.Current.Judging == nil || e.Current.Judging.State != JudgingFailed || len(e.Current.Parts) != 4 { if e.Current.Status != StatusProposed || e.Current.Judging == nil || e.Current.Judging.State != JudgingFailed || len(e.Current.Parts) != 4 {
t.Fatalf("%v: %s, %+v, %d parts", said, e.Current.Status, e.Current.Judging, len(e.Current.Parts)) t.Fatalf("%v: %s, %+v, %d parts", said, e.Current.Status, e.Current.Judging, len(e.Current.Parts))
} }
if most.Load() > MostParallelParts || most.Load() < 2 { if most.Load() != 1 || MostParallelParts != 1 {
t.Fatalf("%d judgements at once; at most %d, and the parts run side by side", most.Load(), MostParallelParts) t.Fatalf("%d judgements at once; exactly 1 (the node judges one at a time), const %d", most.Load(), MostParallelParts)
} }
if got := len(w.said.of(EventPartReviewed)); got != 4 || len(w.said.of(EventReviewed)) != 1 { if got := len(w.said.of(EventPartReviewed)); got != 4 || len(w.said.of(EventReviewed)) != 1 {
t.Fatalf("part-reviewed %d, reviewed %d", got, len(w.said.of(EventReviewed))) t.Fatalf("part-reviewed %d, reviewed %d", got, len(w.said.of(EventReviewed)))