Drop the plan state from the store and the assignments: migration 0108 and placement-only assignments (release 6, issue 1945 B9, B4)

This commit is contained in:
2026-10-24 16:42:02 +02:00
parent 96d7784bce
commit 788fb681ec
110 changed files with 512 additions and 10584 deletions
+27 -22
View File
@@ -49,23 +49,23 @@ func TestABuildIsKeptWholeAndReadBackWithItsReuseKeyAndWhatItPublished(t *testin
func TestAWriteAgainstAMovedRevisionIsRefusedAndNothingIsLaidOver(t *testing.T) {
ctx := context.Background()
c := InMemory(nil)
first, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"})
first, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"})
if err != nil {
t.Fatal(err)
}
if _, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes"}); !errors.Is(err, ErrExists) {
t.Fatalf("a create of a key that holds a value answered %v", err)
}
second, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c2"}, first)
second, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c2"}, first)
if err != nil {
t.Fatal(err)
}
// A writer that read the first revision writes now.
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "stale"}, first); !errors.Is(err, ErrMoved) {
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "stale"}, first); !errors.Is(err, ErrMoved) {
t.Fatalf("a write at a moved revision answered %v", err)
}
got, _, _ := c.Assignments.Get(ctx, "anchor.notes")
if got.Value.Commit != "c2" || got.Revision != second {
if got.Value.RequiredBy != "c2" || got.Revision != second {
t.Fatalf("the key that moved was laid over: %+v at %d", got.Value, got.Revision)
}
}
@@ -91,8 +91,8 @@ func TestNoKeyOfTheChainIsEverRemoved(t *testing.T) {
}
ctx := context.Background()
c := InMemory(nil)
rev, _ := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"})
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"}, rev); err != nil {
rev, _ := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"})
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"}, rev); err != nil {
t.Fatal(err)
}
keys, err := c.Assignments.Keys(ctx)
@@ -190,31 +190,36 @@ func TestARolloutNamesEveryAssignmentItChangedWithBuildBeforeAndAfter(t *testing
}
}
// **An assignment names its build, artifact or package, commit and rollout**, and keeps the fields its readers read
// under the names they read them by (ADR 0408 §3).
func TestAnAssignmentNamesBuildArtifactCommitAndRollout(t *testing.T) {
// **An assignment is placement only** (ADR 0539 §12): the node, the module, since when, what requires it and its
// provisioning plan; no build, artifact, package, commit, rollout or time since is written in it, and a value of before
// release 6 that names them is read with them ignored.
func TestAnAssignmentIsPlacementOnly(t *testing.T) {
a := Assignment{Node: "anchor", Module: "notes", Assigned: at(3), RequiredBy: "wiki",
Provisioning: json.RawMessage(`{"plan":1}`), Build: "b2", Artifact: "sha256:bb", Commit: "c2", Rollout: "r1", Since: at(4)}
Provisioning: json.RawMessage(`{"plan":1}`)}
raw, _ := json.Marshal(a)
for _, want := range []string{`"node":"anchor"`, `"module":"notes"`, `"assigned":"2026-10-18T03:00:00Z"`,
`"required-by":"wiki"`, `"provisioning":{"plan":1}`, `"build":"b2"`, `"artifact":"sha256:bb"`, `"commit":"c2"`,
`"rollout":"r1"`, `"since":"2026-10-18T04:00:00Z"`} {
`"required-by":"wiki"`, `"provisioning":{"plan":1}`} {
if !strings.Contains(string(raw), want) {
t.Errorf("the assignment's value lacks %s: %s", want, raw)
}
}
for _, not := range []string{`"build"`, `"artifact"`, `"package"`, `"commit"`, `"rollout"`, `"since"`, `"pulled-in"`, `"sent-unknown"`} {
if strings.Contains(string(raw), not) {
t.Errorf("the assignment's value names %s: %s", not, raw)
}
}
if a.Key() != "anchor.notes" {
t.Errorf("key %s", a.Key())
}
// An assignment of today carries none of the new fields, and says none: a reader of today reads the bytes it did.
raw, _ = json.Marshal(Assignment{Node: "anchor", Module: "notes", Assigned: at(3)})
if string(raw) != `{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z"}` {
t.Errorf("an assignment without a chain is %s", raw)
// A value written before release 6 is read, its chain fields ignored, and written back without them.
var old Assignment
if err := json.Unmarshal([]byte(`{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z","build":"b2","commit":"c2",`+
`"rollout":"r1","since":"2026-10-18T04:00:00Z","pulled-in":true}`), &old); err != nil {
t.Fatal(err)
}
// A package in place of an artifact.
raw, _ = json.Marshal(Assignment{Node: "a", Module: "m", Package: &Package{Name: "n", Version: "1"}})
if !strings.Contains(string(raw), `"package":{"name":"n","version":"1"}`) {
t.Errorf("the package is %s", raw)
raw, _ = json.Marshal(old)
if string(raw) != `{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z"}` {
t.Errorf("an old value written again is %s", raw)
}
}
@@ -341,7 +346,7 @@ func TestAnEmptyBucketIsReadAsEmpty(t *testing.T) {
func TestAnEndedAssignmentIsNoAssignmentAndStaysInTheBucket(t *testing.T) {
ctx := context.Background()
c := InMemory(nil)
rev, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Assigned: at(1), Commit: "c1"})
rev, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Assigned: at(1), RequiredBy: "c1"})
if err != nil {
t.Fatal(err)
}
@@ -355,7 +360,7 @@ func TestAnEndedAssignmentIsNoAssignmentAndStaysInTheBucket(t *testing.T) {
t.Fatal(err)
}
got, found, _ := c.Assignments.Get(ctx, "anchor.notes")
if !found || got.Value.Stands() || got.Value.Commit != "c1" || got.Value.Ended.IsZero() {
if !found || got.Value.Stands() || got.Value.RequiredBy != "c1" || got.Value.Ended.IsZero() {
t.Fatalf("the ended value is %+v (found %v)", got.Value, found)
}
if history, _ := c.Assignments.History(ctx, "anchor.notes"); len(history) != 2 || !history[0].Value.Stands() {