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.
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
// 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 }
|
||||
Reference in New Issue
Block a user