Files
mesh-controller/internal/chain/records.go
T
jschoubben fc55785956 Add the chain package and its buckets: builds, rollouts and assignments with history 64 (issue 1089)
internal/chain holds typed Build, Rollout and Assignment and a Backend with no delete or purge, in memory and on the bus. The builds and rollouts buckets are asserted with history 64, no age and values up to just under a mebibyte; the assignments bucket gets the same, keeping its marker age because a stream cannot be made to disallow message ages. Migration 0104 makes the one-row chain_moved switch. The controller keeps no consolidated schema, so 0104 is the whole schema change. Nothing reads the buckets yet.
2026-10-18 02:39:11 +02:00

148 lines
6.1 KiB
Go

// Package chain keeps the controller's chain on the bus alone (novox/hq ADR 0408, design 47): module, commit, build,
// published artifact or package, rollout and assignment are one chain, a bucket each of the bus's key-value store,
// each the only source of its kind, written by the controller that holds the lease by compare-and-set.
//
// **No key is removed.** A Backend has no delete and no purge (ADR 0408 §4): an assignment of a module taken off its
// node is kept, saying so. **A value is never cut** (§6): one over the largest the bus holds is refused, and the key
// stays as it was. **Each key keeps its earlier values** (§5), read back with History.
package chain
import (
"encoding/json"
"time"
)
// Ref names a build and the commit it was made from: one end of a change.
type Ref struct {
Build string `json:"build,omitempty"`
Commit string `json:"commit,omitempty"`
}
// Package is a release a build published to the package registry.
type Package struct {
Name string `json:"name"`
Version string `json:"version"`
}
// Published is what a build published: an artifact by its digest, or a package release by name and version.
type Published struct {
Artifact string `json:"artifact,omitempty"`
Package *Package `json:"package,omitempty"`
}
// Artifact is one thing a build made.
type Artifact struct {
Name string `json:"name"`
Kind string `json:"kind"`
Reference string `json:"reference"`
}
// ReadRepository is a repository a build read source from besides the module's own.
type ReadRepository struct {
Repository string `json:"repository"`
Ref string `json:"ref,omitempty"`
Paths []string `json:"paths,omitempty"`
Own bool `json:"own,omitempty"`
}
// Source is the build source a build read in one repository.
type Source struct {
Repository string `json:"repository,omitempty"`
Ref string `json:"ref,omitempty"`
Paths []string `json:"paths"`
}
// The states of a build record. A record in state asked is a request that no outcome has answered (issue 1091); one
// without a state is an outcome.
const BuildAsked = "asked"
// Build is one attempt, whichever way it went, kept under its id. It names its module, its repository and commit, its
// reuse key (novox/hq ADR 0350) and what it published (ADR 0408 §1).
type Build struct {
ID string `json:"id"`
State string `json:"state,omitempty"`
Repository string `json:"repository"`
Ref string `json:"ref,omitempty"`
Module string `json:"module,omitempty"`
Commit string `json:"commit,omitempty"`
On string `json:"on,omitempty"`
Path string `json:"path,omitempty"`
Manifest json.RawMessage `json:"manifest,omitempty"`
Against []string `json:"against,omitempty"`
Mirrored []string `json:"mirrored,omitempty"`
Read []ReadRepository `json:"read,omitempty"`
Sources []Source `json:"sources,omitempty"`
SourceFingerprint string `json:"source-fingerprint,omitempty"`
Failed string `json:"failed,omitempty"`
Made []Artifact `json:"made,omitempty"`
Asked time.Time `json:"asked,omitzero"`
At time.Time `json:"at,omitzero"`
ReuseKey string `json:"reuse-key,omitempty"`
Published *Published `json:"published,omitempty"`
}
// Commit is one repository's commit a rollout carries.
type Commit struct {
Repository string `json:"repository"`
Branch string `json:"branch,omitempty"`
Commit string `json:"commit"`
Merged time.Time `json:"merged,omitzero"`
}
// Change is one assignment a rollout changed: the build and commit it ran before and the ones it runs after.
type Change struct {
Node string `json:"node"`
Module string `json:"module"`
Before Ref `json:"before"`
After Ref `json:"after"`
}
// Step is one tier sent to one machine.
type Step struct {
Tier int `json:"tier"`
Node string `json:"node"`
Sent *time.Time `json:"sent,omitempty"`
Reported *time.Time `json:"reported,omitempty"`
}
// Links are the fields a rollout gains on the chain: the builds it carried, the machine steps it has taken and the
// assignments it changed, each with the build before and after. The controller's plan embeds them, so the plan's own
// fields and these are one value (ADR 0408 §1).
type Links struct {
Builds []string `json:"builds,omitempty"`
Steps []Step `json:"steps,omitempty"`
Changed []Change `json:"changed,omitempty"`
}
// Rollout is the controller's record of one batch's delivery, kept under the batch's id: the commit it fixed per
// repository, its tiers, the builds it carried and the assignments it changed (ADR 0408 §1). The controller's plan
// carries more (its modules, its times, its backups) beside these, under the same key.
type Rollout struct {
ID string `json:"id"`
State string `json:"state,omitempty"`
Commits []Commit `json:"commits,omitempty"`
Tiers [][]string `json:"tiers,omitempty"`
Links
}
// Assignment is one module on one node, kept under `<node>.<module>`. The first five fields are the ones its readers
// have always read, with the names they have always had (novox/hq ADR 0408 §3); the rest name the chain: the build, the
// artifact (by digest) or the package it runs, its commit, the rollout that put it there and since when.
type Assignment struct {
Node string `json:"node"`
Module string `json:"module"`
Assigned time.Time `json:"assigned,omitzero"`
RequiredBy string `json:"required-by,omitempty"`
Provisioning json.RawMessage `json:"provisioning,omitempty"`
Build string `json:"build,omitempty"`
Artifact string `json:"artifact,omitempty"`
Package *Package `json:"package,omitempty"`
Commit string `json:"commit,omitempty"`
Rollout string `json:"rollout,omitempty"`
Since time.Time `json:"since,omitzero"`
}
// Key is an assignment's key.
func (a Assignment) Key() string { return a.Node + "." + a.Module }