Keep builds on the bus under their module, so no lookup reads the bucket whole (issue 1121, ADR 0427)
mesh/merge-gate head c79591531575 merged into trunk aa02e7bf4e78 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head c79591531575 merged into trunk aa02e7bf4e78 — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/merge-gate head c79591531575 merged into trunk aa02e7bf4e78 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head c79591531575 merged into trunk aa02e7bf4e78 — pass: its merge-check.sh passed
mesh/delivery delivered
Milestone 5 moved 8,599 build records onto the bus under bare build ids, each carrying its module's whole manifest. Every build lookup then read the whole bucket, and a delivery plan's send did that per module per machine while it held the plans and the machine's declaration: the send of build-agent never finished, and every other act and the status waited behind it. Builds now live under <module>.build.<id> (requests under req.<id>, id.<id> names a build's module), with pointer keys newest, worked, held, commit.<sha> and source.<reuse key> that move only to a newer build and are read as hints, repaired when wrong. Manifests are kept once in the same bucket under manifest.sha256-<hex>, so no grant the running bus lacks is needed. The old keys are laid out once at start, idempotently, and left unread. The calls a plan look makes on the silent clocks while it holds the plans are bounded, since the vendored kv.Keys ignores its context.
This commit is contained in:
+68
-1
@@ -128,6 +128,60 @@ func (s Bucket[T]) All(ctx context.Context) (map[string]Kept[T], error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Filtered is every record whose key matches a subject pattern, by key, read in one pass of a watch the server filters.
|
||||
func (s Bucket[T]) Filtered(ctx context.Context, filter string) (map[string]Kept[T], error) {
|
||||
ctx, stop := context.WithCancel(ctx)
|
||||
defer stop()
|
||||
w, err := s.b.WatchFiltered(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]Kept[T]{}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("reading %s: %w", filter, ctx.Err())
|
||||
case e, open := <-w:
|
||||
if !open {
|
||||
return nil, errors.New("the bucket stopped answering before it was read whole")
|
||||
}
|
||||
if e.Caught {
|
||||
return out, nil
|
||||
}
|
||||
k, err := decode[T](e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[e.Key] = k
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FilteredRaw is Filtered for keys that hold bytes of their own (a pointer holds a build's id), by key.
|
||||
func (s Bucket[T]) FilteredRaw(ctx context.Context, filter string) (map[string]Entry, error) {
|
||||
ctx, stop := context.WithCancel(ctx)
|
||||
defer stop()
|
||||
w, err := s.b.WatchFiltered(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]Entry{}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("reading %s: %w", filter, ctx.Err())
|
||||
case e, open := <-w:
|
||||
if !open {
|
||||
return nil, errors.New("the bucket stopped answering before it was read whole")
|
||||
}
|
||||
if e.Caught {
|
||||
return out, nil
|
||||
}
|
||||
out[e.Key] = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// History is a key's earlier records and its current one, oldest first.
|
||||
func (s Bucket[T]) History(ctx context.Context, key string) ([]Kept[T], error) {
|
||||
all, err := s.b.History(ctx, key)
|
||||
@@ -182,10 +236,22 @@ type Chain struct {
|
||||
Rollouts Bucket[Rollout]
|
||||
Assignments Bucket[Assignment]
|
||||
|
||||
// Manifests holds each build's manifest once, under the digest of its bytes (ManifestKey); Kept says it is on the bus. A
|
||||
// chain without it keeps the manifest in the build's record, as the tests' chains do.
|
||||
Manifests Bucket[json.RawMessage]
|
||||
Kept bool
|
||||
|
||||
rollouts Backend
|
||||
holds Holds
|
||||
}
|
||||
|
||||
// WithManifests gives the chain its manifests bucket.
|
||||
func (c *Chain) WithManifests(b Backend) *Chain {
|
||||
c.Manifests = Bucket[json.RawMessage]{b: b, holds: c.holds}
|
||||
c.Kept = true
|
||||
return c
|
||||
}
|
||||
|
||||
// RolloutsOf is the rollouts bucket typed as the controller's plan, which carries more than the chain's Rollout names:
|
||||
// the same keys and values, read and written as the plan.
|
||||
func RolloutsOf[T any](c *Chain) Bucket[T] { return Bucket[T]{c.rollouts, c.holds} }
|
||||
@@ -206,5 +272,6 @@ func InMemory(holds Holds) *Chain {
|
||||
if holds == nil {
|
||||
holds = func(context.Context) error { return nil }
|
||||
}
|
||||
return New(NewMemory(), NewMemory(), NewMemory(), holds)
|
||||
builds := NewMemory()
|
||||
return New(builds, NewMemory(), NewMemory(), holds).WithManifests(builds)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user