Keep rollouts and the merges they answer in the rollouts bucket (issue 1092)

Once chain_moved records the kind, a plan is a key of the rollouts bucket under its id and the open batch is the same key in state assembling. A save refuses a copy another save moved since (the plan's own Revision, kept in its value, counts saves) and keeps the merges the record holds, so a copy read before a merge moved cannot lay it back. The merges a batch or walk answers are the record's held field, with the columns the table had; a merge no plan answers stays, flagged, in the record that held it last, or in the record kept for those. A merge moved to a plan is written to the receiving record first and then taken from the giving one; one found in both is read from the one it entered last and repaired at the next cut. Plans and merges are read from a view kept by one watch of the bucket. A bus that does not answer, a lease lost and a key moved are now not-now like the store being away, so a merge whose plan could not be written is held and handed over again, never acknowledged. The start moves release_plan and batched_merge into the bucket, one kind, counted against both tables.
This commit is contained in:
2026-10-18 03:06:50 +02:00
parent e0fb241263
commit 275ddd76e8
21 changed files with 1939 additions and 40 deletions
+13 -2
View File
@@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"regexp"
"slices"
"sort"
@@ -38,6 +39,8 @@ type Inventory struct {
// in the tables as before.
chain *chain.Chain
moved *movedKinds
// recorded, when set, takes the durations a save of the chain measures in place of the store: a test with no store.
recorded func(context.Context, Duration) error
}
// Open connects to the inventory store.
@@ -46,10 +49,18 @@ func Open(ctx context.Context) (*Inventory, error) {
if err != nil {
return nil, err
}
return &Inventory{store: s, moved: &movedKinds{}}, nil
inv := &Inventory{store: s, moved: &movedKinds{}}
// A test's store has the chain a test made for it in memory, shared by every inventory opened on that store.
if c, ok := testChains.Load(os.Getenv(store.Variable(Name))); ok {
inv.chain = c.(*chain.Chain)
}
return inv, nil
}
func (i *Inventory) Close() { i.store.Close() }
func (i *Inventory) Close() {
i.stopViews()
i.store.Close()
}
// Ready waits for the database to answer.
func (i *Inventory) Ready(ctx context.Context, within time.Duration) error {